• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }