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