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