1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <stdio.h>
17 #include <string.h>
18 #include <signal.h>
19 #include <sys/wait.h>
20 #include "fortify_test.h"
21 #include "test.h"
22
23 #define EXPECT_EQ(a, b) \
24 do { \
25 if ((a) != (b)) \
26 t_error("failed!\n"); \
27 } while (0)
28
29 #define EXPECT_STREQ(a, b) \
30 do { \
31 size_t minlen = strlen(a) >= strlen(b) ? strlen(b) : strlen(a); \
32 if (strncmp(a, b, minlen) != 0) \
33 t_error("failed\n"); \
34 } while (0)
35
36 #define EXPECT_TRUE(c) \
37 do { \
38 if (!(c)) \
39 t_error("failed!\n"); \
40 } while (0)
41
42 /**
43 * @tc.name : fread
44 * @tc.desc : normal use
45 * @tc.level : Level 0
46 */
stdio_dynamic_chk_001(void)47 static void stdio_dynamic_chk_001(void)
48 {
49 char hello_world[] = "hello world!";
50 FILE *fp = fmemopen(hello_world, sizeof(hello_world), "r");
51 EXPECT_TRUE(fp);
52
53 const int bufferSize = 14;
54 char buf[bufferSize]; // > sizeof(hello_world)
55 EXPECT_EQ(1u, fread(buf, sizeof(hello_world), 1, fp));
56 EXPECT_STREQ(hello_world, buf);
57
58 fclose(fp);
59 }
60
61 /**
62 * @tc.name : fread
63 * @tc.desc : normal use
64 * @tc.level : Level 0
65 */
stdio_dynamic_chk_002(void)66 static void stdio_dynamic_chk_002(void)
67 {
68 FILE *fp = fopen("/dev/zero", "r");
69 EXPECT_TRUE(fp);
70
71 setvbuf(fp, NULL, _IONBF, 0);
72
73 const int bufferSize = 65*1024;
74 char buf[bufferSize];
75 memset(buf, 0xff, sizeof(buf));
76
77 size_t read_size = 64*1024;
78 size_t count_size = 1024;
79 for (size_t i = 0; i < count_size; ++i) {
80 EXPECT_EQ(1u, fread(buf, read_size, 1, fp));
81 }
82
83 // The first 64*1024 should be assigned
84 for (size_t i = 0; i < read_size; ++i) {
85 EXPECT_EQ('\0', buf[i]);
86 }
87
88 // What's left is its original data
89 for (size_t i = read_size; i < bufferSize; ++i) {
90 EXPECT_EQ('\xff', buf[i]);
91 }
92
93 }
94
95 /**
96 * @tc.name : fread
97 * @tc.desc : Exceed the buffer range and reach dynamic monitoring conditions
98 * @tc.level : Level 2
99 */
stdio_dynamic_chk_003(void)100 static void stdio_dynamic_chk_003(void)
101 {
102 struct sigaction sigabrt = {
103 .sa_handler = SignalHandler,
104 };
105 sigaction(SIGABRT, &sigabrt, NULL);
106
107 const int bufferSize = 1;
108 char buf[bufferSize];
109 size_t ct = atoi("2");
110 FILE* fp = fopen("/dev/null", "r");
111
112 int status;
113 int pid = fork();
114 switch (pid) {
115 case -1:
116 t_error("fork failed: %d\n", __LINE__);
117 break;
118 case 0:
119 fread(buf, 1, ct, fp);
120 break;
121 default:
122 waitpid(pid, &status, WUNTRACED);
123 TEST(WIFEXITED(status) == 0);
124 TEST(WIFSTOPPED(status) == 1);
125 TEST(WSTOPSIG(status) == SIGSTOP);
126 kill(pid, SIGCONT);
127 break;
128 }
129 fclose(fp);
130 }
131
132 /**
133 * @tc.name : fwrite
134 * @tc.desc : Exceed the buffer range and reach dynamic monitoring conditions
135 * @tc.level : Level 2
136 */
stdio_dynamic_chk_004(void)137 static void stdio_dynamic_chk_004(void)
138 {
139 struct sigaction sigabrt = {
140 .sa_handler = SignalHandler,
141 };
142 sigaction(SIGABRT, &sigabrt, NULL);
143
144 size_t ct = atoi("2");
145 FILE* fp = fopen("/dev/null", "w");
146
147 const int bufferSize = 1;
148 char buf[bufferSize];
149
150 int status;
151 int pid = fork();
152 switch (pid) {
153 case -1:
154 t_error("fork failed: %d\n", __LINE__);
155 break;
156 case 0:
157 fwrite(buf, 1, ct, fp);
158 break;
159 default:
160 waitpid(pid, &status, WUNTRACED);
161 TEST(WIFEXITED(status) == 0);
162 TEST(WIFSTOPPED(status) == 1);
163 TEST(WSTOPSIG(status) == SIGSTOP);
164 kill(pid, SIGCONT);
165 break;
166 }
167 fclose(fp);
168 }
169
170 /**
171 * @tc.name : fgets
172 * @tc.desc : Normal function
173 * @tc.level : Level 0
174 */
stdio_dynamic_chk_005(void)175 static void stdio_dynamic_chk_005(void)
176 {
177 char hello_world[] = "hello world!";
178 FILE *fp = fmemopen(hello_world, sizeof(hello_world), "r");
179 EXPECT_TRUE(fp);
180
181 const int bufferSize = 16;
182 char buf[bufferSize];
183 char *get = fgets(buf, sizeof(buf), fp);
184 EXPECT_TRUE(get != NULL);
185 EXPECT_TRUE(strcmp(hello_world, get) == 0);
186 fclose(fp);
187 }
188
189 /**
190 * @tc.name : fgets
191 * @tc.desc : Get newline and end position as normal
192 * @tc.level : Level 0
193 */
stdio_dynamic_chk_006(void)194 static void stdio_dynamic_chk_006(void)
195 {
196 char hello_world[] = "hello world!\nhello boy!\0";
197 FILE *fp = fmemopen(hello_world, sizeof(hello_world), "r");
198 EXPECT_TRUE(fp);
199
200 const int bufferSize = 16;
201 char buf[bufferSize];
202 char *get1 = fgets(buf, sizeof("hello"), fp);
203 EXPECT_TRUE(get1 != NULL);
204 EXPECT_TRUE(strcmp("hello", get1) == 0);
205
206 memset(buf,0x00,sizeof(buf));
207 char *get2 = fgets(buf, sizeof(buf), fp);
208 EXPECT_TRUE(get2 != NULL);
209
210 memset(buf,0x00,sizeof(buf));
211 char *get3 = fgets(buf, sizeof(buf), fp);
212 EXPECT_TRUE(get3 != NULL);
213 EXPECT_TRUE(strcmp("hello boy!", get3) == 0);
214 fclose(fp);
215 }
216
217 /**
218 * @tc.name : fgets
219 * @tc.desc : The size of reads is greater than the capacity of buf
220 * @tc.level : Level 2
221 */
stdio_dynamic_chk_007(void)222 static void stdio_dynamic_chk_007(void)
223 {
224 struct sigaction sigabrt = {
225 .sa_handler = SignalHandler,
226 };
227 sigaction(SIGABRT, &sigabrt, NULL);
228
229 char hello_world[] = "hello world!";
230 FILE *fp = fmemopen(hello_world, sizeof(hello_world), "r");
231
232 const int bufferSize = 16;
233 char buf[bufferSize];
234 size_t n = atoi("18");
235 int status;
236 int pid = fork();
237 switch (pid) {
238 case -1:
239 t_error("fork failed: %d\n", __LINE__);
240 break;
241 case 0:
242 fgets(buf, n, fp);
243 break;
244 default:
245 waitpid(pid, &status, WUNTRACED);
246 TEST(WIFEXITED(status) == 0);
247 TEST(WIFSTOPPED(status) == 1);
248 TEST(WSTOPSIG(status) == SIGSTOP);
249 kill(pid, SIGCONT);
250 break;
251 }
252 fclose(fp);
253 }
254
255 /**
256 * @tc.name : sprintf
257 * @tc.desc : Normal call test
258 * @tc.level : Level 0
259 */
stdio_dynamic_chk_008(void)260 static void stdio_dynamic_chk_008(void)
261 {
262 char buf[] = "world";
263 sprintf(buf, "hello");
264 EXPECT_TRUE(strcmp(buf, "hello") == 0);
265 }
266
267 /**
268 * @tc.name : sprintf
269 * @tc.desc : Normal call test
270 * @tc.level : Level 0
271 */
stdio_dynamic_chk_009(void)272 static void stdio_dynamic_chk_009(void)
273 {
274 const int bufferSize = 20;
275 char buf[bufferSize];
276 sprintf(buf, "hello : %s", "world!");
277
278 char value[] = "hello : world!";
279 EXPECT_TRUE(strcmp(buf, value) == 0);
280 }
281
282
283 /**
284 * @tc.name : sprintf
285 * @tc.desc : sprintf beyond capacity
286 * @tc.level : Level 2
287 */
stdio_dynamic_chk_010(void)288 static void stdio_dynamic_chk_010(void)
289 {
290 const int bufferSize = 6;
291 char buf[bufferSize];
292
293 struct sigaction sigabrt = {
294 .sa_handler = SignalHandler,
295 };
296 sigaction(SIGABRT, &sigabrt, NULL);
297
298 int status;
299 int pid = fork();
300 switch (pid) {
301 case -1:
302 t_error("fork failed: %d\n", __LINE__);
303 break;
304 case 0:
305 sprintf(buf, "hello : %s", "world!");
306 break;
307 default:
308 waitpid(pid, &status, WUNTRACED);
309 TEST(WIFEXITED(status) == 0);
310 TEST(WIFSTOPPED(status) == 1);
311 TEST(WSTOPSIG(status) == SIGSTOP);
312 kill(pid, SIGCONT);
313 break;
314 }
315 }
316
317 /**
318 * @tc.name : snprintf
319 * @tc.desc : snprintf beyond capacity
320 * @tc.level : Level 2
321 */
322
stdio_dynamic_chk_011(void)323 static void stdio_dynamic_chk_011(void)
324 {
325 const int bufferSize = 6;
326 char buf[bufferSize];
327
328 struct sigaction sigabrt = {
329 .sa_handler = SignalHandler,
330 };
331 sigaction(SIGABRT, &sigabrt, NULL);
332
333 int printSize = 10;
334 int status;
335 int pid = fork();
336 switch (pid) {
337 case -1:
338 t_error("fork failed: %d\n", __LINE__);
339 break;
340 case 0: // 10 > sizeof buf
341 snprintf(buf, printSize, "hello : %s", "world!");
342 break;
343 default:
344 waitpid(pid, &status, WUNTRACED);
345 TEST(WIFEXITED(status) == 0);
346 TEST(WIFSTOPPED(status) == 1);
347 TEST(WSTOPSIG(status) == SIGSTOP);
348 kill(pid, SIGCONT);
349 break;
350 }
351 }
352
353
vsnprintf_test(const char * format,...)354 static int vsnprintf_test(const char* format, ...)
355 {
356 const int bufferSize = 6;
357 char buf[bufferSize];
358 int printSize = 10;
359 va_list va;
360 va_start(va, format);
361 int result = vsnprintf(buf, printSize, format, va);
362 va_end(va);
363 return result;
364 }
365
vsprintf_test(const char * format,...)366 static int vsprintf_test(const char* format, ...)
367 {
368 const int bufferSize = 6;
369 char buf[bufferSize];
370 va_list va;
371 va_start(va, format);
372 int result = vsprintf(buf, format, va);
373 va_end(va);
374 return result;
375 }
376
377 /**
378 * @tc.name : vsnprintf
379 * @tc.desc : vsnprintf beyond capacity
380 * @tc.level : Level 2
381 */
stdio_dynamic_chk_012(void)382 static void stdio_dynamic_chk_012(void)
383 {
384 struct sigaction sigabrt = {
385 .sa_handler = SignalHandler,
386 };
387 sigaction(SIGABRT, &sigabrt, NULL);
388
389 int status;
390 int pid = fork();
391 switch (pid) {
392 case -1:
393 t_error("fork failed: %d\n", __LINE__);
394 break;
395 case 0:
396 vsnprintf_test("hello : %s", "world!");
397 break;
398 default:
399 waitpid(pid, &status, WUNTRACED);
400 TEST(WIFEXITED(status) == 0);
401 TEST(WIFSTOPPED(status) == 1);
402 TEST(WSTOPSIG(status) == SIGSTOP);
403 kill(pid, SIGCONT);
404 break;
405 }
406 }
407
408 /**
409 * @tc.name : vsprsintf
410 * @tc.desc : vsprintf beyond capacity
411 * @tc.level : Level 2
412 */
stdio_dynamic_chk_013(void)413 static void stdio_dynamic_chk_013(void)
414 {
415 struct sigaction sigabrt = {
416 .sa_handler = SignalHandler,
417 };
418 sigaction(SIGABRT, &sigabrt, NULL);
419
420 int status;
421 int pid = fork();
422 switch (pid) {
423 case -1:
424 t_error("fork failed: %d\n", __LINE__);
425 break;
426 case 0:
427 vsprintf_test("%s", "0123456789");
428 break;
429 default:
430 waitpid(pid, &status, WUNTRACED);
431 TEST(WIFEXITED(status) == 0);
432 TEST(WIFSTOPPED(status) == 1);
433 TEST(WSTOPSIG(status) == SIGSTOP);
434 kill(pid, SIGCONT);
435 break;
436 }
437 }
438
main()439 int main()
440 {
441 stdio_dynamic_chk_001();
442 stdio_dynamic_chk_002();
443 stdio_dynamic_chk_003();
444 stdio_dynamic_chk_004();
445 stdio_dynamic_chk_005();
446 stdio_dynamic_chk_006();
447 stdio_dynamic_chk_007();
448 stdio_dynamic_chk_008();
449 stdio_dynamic_chk_009();
450 stdio_dynamic_chk_010();
451 stdio_dynamic_chk_011();
452 stdio_dynamic_chk_012();
453 stdio_dynamic_chk_013();
454
455 return t_status;
456 }