modernc.org/ccgo/v3@v3.16.14/lib/testdata/gcc-9.1.0/gcc/testsuite/gcc.c-torture/execute/builtins/memmove-chk.c (about) 1 /* Copyright (C) 2004, 2005 Free Software Foundation. 2 3 Ensure builtin __memcpy_chk performs correctly. */ 4 5 extern void abort (void); 6 typedef __SIZE_TYPE__ size_t; 7 extern size_t strlen(const char *); 8 extern void *memcpy (void *, const void *, size_t); 9 extern void *memmove (void *, const void *, size_t); 10 extern int memcmp (const void *, const void *, size_t); 11 12 #include "chk.h" 13 14 const char s1[] = "123"; 15 char p[32] = ""; 16 volatile char *s2 = "defg"; /* prevent constant propagation to happen when whole program assumptions are made. */ 17 volatile char *s3 = "FGH"; /* prevent constant propagation to happen when whole program assumptions are made. */ 18 volatile size_t l1 = 1; /* prevent constant propagation to happen when whole program assumptions are made. */ 19 20 void 21 __attribute__((noinline)) 22 test1 (void) 23 { 24 int i; 25 26 #if defined __i386__ || defined __x86_64__ 27 /* The functions below might not be optimized into direct stores on all 28 arches. It depends on how many instructions would be generated and 29 what limits the architecture chooses in STORE_BY_PIECES_P. */ 30 memmove_disallowed = 1; 31 memcpy_disallowed = 1; 32 #endif 33 34 /* All the memmove calls in this routine except last have fixed length, so 35 object size checking should be done at compile time if optimizing. */ 36 chk_calls = 0; 37 38 if (memmove (p, "ABCDE", 6) != p || memcmp (p, "ABCDE", 6)) 39 abort (); 40 if (memmove (p + 16, "VWX" + 1, 2) != p + 16 41 || memcmp (p + 16, "WX\0\0", 5)) 42 abort (); 43 if (memmove (p + 1, "", 1) != p + 1 || memcmp (p, "A\0CDE", 6)) 44 abort (); 45 if (memmove (p + 3, "FGHI", 4) != p + 3 || memcmp (p, "A\0CFGHI", 8)) 46 abort (); 47 48 i = 8; 49 memmove (p + 20, "qrstu", 6); 50 memmove (p + 25, "QRSTU", 6); 51 if (memmove (p + 25 + 1, s1, 3) != p + 25 + 1 52 || memcmp (p + 25, "Q123U", 6)) 53 abort (); 54 55 if (memmove (memmove (p, "abcdEFG", 4) + 4, "efg", 4) != p + 4 56 || memcmp (p, "abcdefg", 8)) 57 abort(); 58 59 /* Test at least one instance of the __builtin_ style. We do this 60 to ensure that it works and that the prototype is correct. */ 61 if (__builtin_memmove (p, "ABCDE", 6) != p || memcmp (p, "ABCDE", 6)) 62 abort (); 63 64 memmove (p + 5, s3, 1); 65 if (memcmp (p, "ABCDEFg", 8)) 66 abort (); 67 68 memmove_disallowed = 0; 69 memcpy_disallowed = 0; 70 if (chk_calls) 71 abort (); 72 chk_calls = 0; 73 74 memmove (p + 6, s1 + 1, l1); 75 if (memcmp (p, "ABCDEF2", 8)) 76 abort (); 77 78 /* The above memmove copies into an object with known size, but 79 unknown length, so it should be a __memmove_chk call. */ 80 if (chk_calls != 1) 81 abort (); 82 } 83 84 long buf1[64]; 85 char *buf2 = (char *) (buf1 + 32); 86 long buf5[20]; 87 char buf7[20]; 88 89 void 90 __attribute__((noinline)) 91 test2_sub (long *buf3, char *buf4, char *buf6, int n) 92 { 93 int i = 0; 94 95 /* All the memmove/__builtin_memmove/__builtin___memmove_chk 96 calls in this routine are either fixed length, or have 97 side-effects in __builtin_object_size arguments, or 98 dst doesn't point into a known object. */ 99 chk_calls = 0; 100 101 /* These should probably be handled by store_by_pieces on most arches. */ 102 if (memmove (buf1, "ABCDEFGHI", 9) != (char *) buf1 103 || memcmp (buf1, "ABCDEFGHI\0", 11)) 104 abort (); 105 106 if (memmove (buf1, "abcdefghijklmnopq", 17) != (char *) buf1 107 || memcmp (buf1, "abcdefghijklmnopq\0", 19)) 108 abort (); 109 110 if (__builtin_memmove (buf3, "ABCDEF", 6) != (char *) buf1 111 || memcmp (buf1, "ABCDEFghijklmnopq\0", 19)) 112 abort (); 113 114 if (__builtin_memmove (buf3, "a", 1) != (char *) buf1 115 || memcmp (buf1, "aBCDEFghijklmnopq\0", 19)) 116 abort (); 117 118 if (memmove ((char *) buf3 + 2, "bcd" + ++i, 2) != (char *) buf1 + 2 119 || memcmp (buf1, "aBcdEFghijklmnopq\0", 19) 120 || i != 1) 121 abort (); 122 123 /* These should probably be handled by move_by_pieces on most arches. */ 124 if (memmove ((char *) buf3 + 4, buf5, 6) != (char *) buf1 + 4 125 || memcmp (buf1, "aBcdRSTUVWklmnopq\0", 19)) 126 abort (); 127 128 if (__builtin_memmove ((char *) buf1 + ++i + 8, (char *) buf5 + 1, 1) 129 != (char *) buf1 + 10 130 || memcmp (buf1, "aBcdRSTUVWSlmnopq\0", 19) 131 || i != 2) 132 abort (); 133 134 if (memmove ((char *) buf3 + 14, buf6, 2) != (char *) buf1 + 14 135 || memcmp (buf1, "aBcdRSTUVWSlmnrsq\0", 19)) 136 abort (); 137 138 if (memmove (buf3, buf5, 8) != (char *) buf1 139 || memcmp (buf1, "RSTUVWXYVWSlmnrsq\0", 19)) 140 abort (); 141 142 if (memmove (buf3, buf5, 17) != (char *) buf1 143 || memcmp (buf1, "RSTUVWXYZ01234567\0", 19)) 144 abort (); 145 146 __builtin_memmove (buf3, "aBcdEFghijklmnopq\0", 19); 147 148 /* These should be handled either by movmemendM or memmove 149 call. */ 150 151 /* buf3 points to an unknown object, so __memmove_chk should not be done. */ 152 if (memmove ((char *) buf3 + 4, buf5, n + 6) != (char *) buf1 + 4 153 || memcmp (buf1, "aBcdRSTUVWklmnopq\0", 19)) 154 abort (); 155 156 /* This call has side-effects in dst, therefore no checking. */ 157 if (__builtin___memmove_chk ((char *) buf1 + ++i + 8, (char *) buf5 + 1, 158 n + 1, os ((char *) buf1 + ++i + 8)) 159 != (char *) buf1 + 11 160 || memcmp (buf1, "aBcdRSTUVWkSmnopq\0", 19) 161 || i != 3) 162 abort (); 163 164 if (memmove ((char *) buf3 + 14, buf6, n + 2) != (char *) buf1 + 14 165 || memcmp (buf1, "aBcdRSTUVWkSmnrsq\0", 19)) 166 abort (); 167 168 i = 1; 169 170 /* These might be handled by store_by_pieces. */ 171 if (memmove (buf2, "ABCDEFGHI", 9) != buf2 172 || memcmp (buf2, "ABCDEFGHI\0", 11)) 173 abort (); 174 175 if (memmove (buf2, "abcdefghijklmnopq", 17) != buf2 176 || memcmp (buf2, "abcdefghijklmnopq\0", 19)) 177 abort (); 178 179 if (__builtin_memmove (buf4, "ABCDEF", 6) != buf2 180 || memcmp (buf2, "ABCDEFghijklmnopq\0", 19)) 181 abort (); 182 183 if (__builtin_memmove (buf4, "a", 1) != buf2 184 || memcmp (buf2, "aBCDEFghijklmnopq\0", 19)) 185 abort (); 186 187 if (memmove (buf4 + 2, "bcd" + i++, 2) != buf2 + 2 188 || memcmp (buf2, "aBcdEFghijklmnopq\0", 19) 189 || i != 2) 190 abort (); 191 192 /* These might be handled by move_by_pieces. */ 193 if (memmove (buf4 + 4, buf7, 6) != buf2 + 4 194 || memcmp (buf2, "aBcdRSTUVWklmnopq\0", 19)) 195 abort (); 196 197 /* Side effect. */ 198 if (__builtin___memmove_chk (buf2 + i++ + 8, buf7 + 1, 1, 199 os (buf2 + i++ + 8)) 200 != buf2 + 10 201 || memcmp (buf2, "aBcdRSTUVWSlmnopq\0", 19) 202 || i != 3) 203 abort (); 204 205 if (memmove (buf4 + 14, buf6, 2) != buf2 + 14 206 || memcmp (buf2, "aBcdRSTUVWSlmnrsq\0", 19)) 207 abort (); 208 209 __builtin_memmove (buf4, "aBcdEFghijklmnopq\0", 19); 210 211 /* These should be handled either by movmemendM or memmove 212 call. */ 213 if (memmove (buf4 + 4, buf7, n + 6) != buf2 + 4 214 || memcmp (buf2, "aBcdRSTUVWklmnopq\0", 19)) 215 abort (); 216 217 /* Side effect. */ 218 if (__builtin___memmove_chk (buf2 + i++ + 8, buf7 + 1, n + 1, 219 os (buf2 + i++ + 8)) 220 != buf2 + 11 221 || memcmp (buf2, "aBcdRSTUVWkSmnopq\0", 19) 222 || i != 4) 223 abort (); 224 225 if (memmove (buf4 + 14, buf6, n + 2) != buf2 + 14 226 || memcmp (buf2, "aBcdRSTUVWkSmnrsq\0", 19)) 227 abort (); 228 229 if (chk_calls) 230 abort (); 231 } 232 233 void 234 __attribute__((noinline)) 235 test2 (void) 236 { 237 long *x; 238 char *y; 239 int z; 240 __builtin_memmove (buf5, "RSTUVWXYZ0123456789", 20); 241 __builtin_memmove (buf7, "RSTUVWXYZ0123456789", 20); 242 __asm ("" : "=r" (x) : "0" (buf1)); 243 __asm ("" : "=r" (y) : "0" (buf2)); 244 __asm ("" : "=r" (z) : "0" (0)); 245 test2_sub (x, y, "rstuvwxyz", z); 246 } 247 248 static const struct foo 249 { 250 char *s; 251 double d; 252 long l; 253 } foo[] = 254 { 255 { "hello world1", 3.14159, 101L }, 256 { "hello world2", 3.14159, 102L }, 257 { "hello world3", 3.14159, 103L }, 258 { "hello world4", 3.14159, 104L }, 259 { "hello world5", 3.14159, 105L }, 260 { "hello world6", 3.14159, 106L } 261 }; 262 263 static const struct bar 264 { 265 char *s; 266 const struct foo f[3]; 267 } bar[] = 268 { 269 { 270 "hello world10", 271 { 272 { "hello1", 3.14159, 201L }, 273 { "hello2", 3.14159, 202L }, 274 { "hello3", 3.14159, 203L }, 275 } 276 }, 277 { 278 "hello world11", 279 { 280 { "hello4", 3.14159, 204L }, 281 { "hello5", 3.14159, 205L }, 282 { "hello6", 3.14159, 206L }, 283 } 284 } 285 }; 286 287 static const int baz[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; 288 289 void 290 __attribute__((noinline)) 291 test3 (void) 292 { 293 const char *s; 294 struct foo f1[sizeof foo/sizeof*foo]; 295 struct bar b1[sizeof bar/sizeof*bar]; 296 int bz[sizeof baz/sizeof*baz]; 297 298 /* All the memmove/__builtin_memmove calls in this routine have fixed 299 length. */ 300 chk_calls = 0; 301 302 /* All the *memmove calls below have src in read-only memory, so all 303 of them should be optimized into memcpy. */ 304 memmove_disallowed = 1; 305 if (memmove (f1, foo, sizeof (foo)) != f1 || memcmp (f1, foo, sizeof (foo))) 306 abort (); 307 if (memmove (b1, bar, sizeof (bar)) != b1 || memcmp (b1, bar, sizeof (bar))) 308 abort (); 309 memmove (bz, baz, sizeof (baz)); 310 if (memcmp (bz, baz, sizeof (baz))) 311 abort (); 312 313 if (memmove (p, "abcde", 6) != p || memcmp (p, "abcde", 6)) 314 abort (); 315 s = s1; 316 if (memmove (p + 2, ++s, 0) != p + 2 || memcmp (p, "abcde", 6) || s != s1 + 1) 317 abort (); 318 if (__builtin_memmove (p + 3, "", 1) != p + 3 || memcmp (p, "abc\0e", 6)) 319 abort (); 320 memmove (p + 2, "fghijk", 4); 321 if (memcmp (p, "abfghi", 7)) 322 abort (); 323 s = s1 + 1; 324 memmove (p + 1, s++, 0); 325 if (memcmp (p, "abfghi", 7) || s != s1 + 2) 326 abort (); 327 __builtin_memmove (p + 4, "ABCDE", 1); 328 if (memcmp (p, "abfgAi", 7)) 329 abort (); 330 331 /* memmove with length 1 can be optimized into memcpy if it can be 332 expanded inline. */ 333 if (memmove (p + 2, p + 3, 1) != p + 2) 334 abort (); 335 if (memcmp (p, "abggAi", 7)) 336 abort (); 337 338 if (chk_calls) 339 abort (); 340 memmove_disallowed = 0; 341 } 342 343 /* Test whether compile time checking is done where it should 344 and so is runtime object size checking. */ 345 void 346 __attribute__((noinline)) 347 test4 (void) 348 { 349 struct A { char buf1[10]; char buf2[10]; } a; 350 char *r = l1 == 1 ? &a.buf1[5] : &a.buf2[4]; 351 char buf3[20]; 352 int i; 353 size_t l; 354 355 /* The following calls should do runtime checking 356 - length is not known, but destination is. */ 357 chk_calls = 0; 358 memmove (a.buf1 + 2, s3, l1); 359 memmove (r, s3, l1 + 1); 360 r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7]; 361 memmove (r, s2, l1 + 2); 362 memmove (r + 2, s3, l1); 363 r = buf3; 364 for (i = 0; i < 4; ++i) 365 { 366 if (i == l1 - 1) 367 r = &a.buf1[1]; 368 else if (i == l1) 369 r = &a.buf2[7]; 370 else if (i == l1 + 1) 371 r = &buf3[5]; 372 else if (i == l1 + 2) 373 r = &a.buf1[9]; 374 } 375 memmove (r, s2, l1); 376 if (chk_calls != 5) 377 abort (); 378 379 /* Following have known destination and known length, 380 so if optimizing certainly shouldn't result in the checking 381 variants. */ 382 chk_calls = 0; 383 memmove (a.buf1 + 2, s3, 1); 384 memmove (r, s3, 2); 385 r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7]; 386 memmove (r, s2, 3); 387 r = buf3; 388 l = 4; 389 for (i = 0; i < 4; ++i) 390 { 391 if (i == l1 - 1) 392 r = &a.buf1[1], l = 2; 393 else if (i == l1) 394 r = &a.buf2[7], l = 3; 395 else if (i == l1 + 1) 396 r = &buf3[5], l = 4; 397 else if (i == l1 + 2) 398 r = &a.buf1[9], l = 1; 399 } 400 memmove (r, s2, 1); 401 /* Here, l is known to be at most 4 and __builtin_object_size (&buf3[16], 0) 402 is 4, so this doesn't need runtime checking. */ 403 memmove (&buf3[16], s2, l); 404 if (chk_calls) 405 abort (); 406 chk_calls = 0; 407 } 408 409 /* Test whether runtime and/or compile time checking catches 410 buffer overflows. */ 411 void 412 __attribute__((noinline)) 413 test5 (void) 414 { 415 struct A { char buf1[10]; char buf2[10]; } a; 416 char buf3[20]; 417 418 chk_fail_allowed = 1; 419 /* Runtime checks. */ 420 if (__builtin_setjmp (chk_fail_buf) == 0) 421 { 422 memmove (&a.buf2[9], s2, l1 + 1); 423 abort (); 424 } 425 if (__builtin_setjmp (chk_fail_buf) == 0) 426 { 427 memmove (&a.buf2[7], s3, strlen (s3) + 1); 428 abort (); 429 } 430 /* This should be detectable at compile time already. */ 431 if (__builtin_setjmp (chk_fail_buf) == 0) 432 { 433 memmove (&buf3[19], "ab", 2); 434 abort (); 435 } 436 chk_fail_allowed = 0; 437 } 438 439 #ifndef MAX_OFFSET 440 #define MAX_OFFSET (sizeof (long long)) 441 #endif 442 443 #ifndef MAX_COPY 444 #define MAX_COPY (10 * sizeof (long long)) 445 #endif 446 447 #ifndef MAX_EXTRA 448 #define MAX_EXTRA (sizeof (long long)) 449 #endif 450 451 #define MAX_LENGTH (MAX_OFFSET + MAX_COPY + MAX_EXTRA) 452 453 /* Use a sequence length that is not divisible by two, to make it more 454 likely to detect when words are mixed up. */ 455 #define SEQUENCE_LENGTH 31 456 457 static union { 458 char buf[MAX_LENGTH]; 459 long long align_int; 460 long double align_fp; 461 } u1, u2; 462 463 void 464 __attribute__((noinline)) 465 test6 (void) 466 { 467 int off1, off2, len, i; 468 char *p, *q, c; 469 470 for (off1 = 0; off1 < MAX_OFFSET; off1++) 471 for (off2 = 0; off2 < MAX_OFFSET; off2++) 472 for (len = 1; len < MAX_COPY; len++) 473 { 474 for (i = 0, c = 'A'; i < MAX_LENGTH; i++, c++) 475 { 476 u1.buf[i] = 'a'; 477 if (c >= 'A' + SEQUENCE_LENGTH) 478 c = 'A'; 479 u2.buf[i] = c; 480 } 481 482 p = memmove (u1.buf + off1, u2.buf + off2, len); 483 if (p != u1.buf + off1) 484 abort (); 485 486 q = u1.buf; 487 for (i = 0; i < off1; i++, q++) 488 if (*q != 'a') 489 abort (); 490 491 for (i = 0, c = 'A' + off2; i < len; i++, q++, c++) 492 { 493 if (c >= 'A' + SEQUENCE_LENGTH) 494 c = 'A'; 495 if (*q != c) 496 abort (); 497 } 498 499 for (i = 0; i < MAX_EXTRA; i++, q++) 500 if (*q != 'a') 501 abort (); 502 } 503 } 504 505 #define TESTSIZE 80 506 507 char srcb[TESTSIZE] __attribute__ ((aligned)); 508 char dstb[TESTSIZE] __attribute__ ((aligned)); 509 510 void 511 __attribute__((noinline)) 512 check (char *test, char *match, int n) 513 { 514 if (memcmp (test, match, n)) 515 abort (); 516 } 517 518 #define TN(n) \ 519 { memset (dstb, 0, n); memmove (dstb, srcb, n); check (dstb, srcb, n); } 520 #define T(n) \ 521 TN (n) \ 522 TN ((n) + 1) \ 523 TN ((n) + 2) \ 524 TN ((n) + 3) 525 526 void 527 __attribute__((noinline)) 528 test7 (void) 529 { 530 int i; 531 532 chk_calls = 0; 533 534 for (i = 0; i < sizeof (srcb); ++i) 535 srcb[i] = 'a' + i % 26; 536 537 T (0); 538 T (4); 539 T (8); 540 T (12); 541 T (16); 542 T (20); 543 T (24); 544 T (28); 545 T (32); 546 T (36); 547 T (40); 548 T (44); 549 T (48); 550 T (52); 551 T (56); 552 T (60); 553 T (64); 554 T (68); 555 T (72); 556 T (76); 557 558 /* All memmove calls in this routine have constant arguments. */ 559 if (chk_calls) 560 abort (); 561 } 562 563 void 564 main_test (void) 565 { 566 #ifndef __OPTIMIZE__ 567 /* Object size checking is only intended for -O[s123]. */ 568 return; 569 #endif 570 __asm ("" : "=r" (l1) : "0" (l1)); 571 test1 (); 572 test2 (); 573 __builtin_memset (p, '\0', sizeof (p)); 574 test3 (); 575 test4 (); 576 test5 (); 577 test6 (); 578 test7 (); 579 }