/* PR middle-end/97023 - missing warning on buffer overflow in chained mempcpy Verify that out of bounds writes by built-ins to objects through pointers returned by other built-ins are diagnosed. { dg-do compile } { dg-options "-O2" } */ #include "range.h" void* malloc (size_t); void* memcpy (void*, const void*, size_t); void* memmove (void*, const void*, size_t); void* mempcpy (void*, const void*, size_t); void sink (void*, ...); void nowarn_memcpy (const void *s) { extern char cpy_a4[4]; unsigned n = sizeof cpy_a4; void *p = cpy_a4; p = memcpy (p, s, n); sink (p); memcpy (p, s, n); sink (p); p = cpy_a4 + 1; p = memcpy (p, s, n - 1); sink (p); memcpy (p, s, n - 1); sink (p); p = cpy_a4 + 2; p = memcpy (p, s, n - 2); sink (p); memcpy (p, s, n - 2); sink (p); p = cpy_a4 + 3; p = memcpy (p, s, n - 3); sink (p); memcpy (p, s, n - 3); sink (p); p = cpy_a4 + 4; p = memcpy (p, s, n - 4); sink (p); memcpy (p, s, n - 4); sink (p); } void nowarn_memcpy_chain (const void *s) { extern char cpy_a8[8]; char *p = cpy_a8; p = memcpy (p + 1, s, 7); sink (p); p = memcpy (p + 2 , s, 5); sink (p); p = memcpy (p + 3 , s, 2); sink (p); p = memcpy (p + 1 , s, 1); sink (p); p = memcpy (p - 7 , s, 8); sink (p); memcpy (p + 1, s, 7); } void warn_memcpy (const void *s) { extern char cpy_a5[5]; // { dg-message "destination object 'cpy_a5'" "note" } unsigned n = sizeof cpy_a5; void *p = cpy_a5; p = memcpy (p, s, n); sink (p); memcpy (p, s, n + 1); // { dg-warning "writing 6 bytes into a region of size 5" } sink (p); p = cpy_a5; p = memcpy (p, s, n); sink (p); memcpy (p, s, n + 1); // { dg-warning "writing 6 bytes into a region of size 5" } sink (p); p = cpy_a5 + 1; p = memcpy (p, s, n - 1); sink (p); memcpy (p, s, n); // { dg-warning "writing 5 bytes into a region of size 4" } sink (p); } void warn_memcpy_chain (const void *s) { extern char cpy_a8[8]; // { dg-message "destination object 'cpy_a8'" "note" } char *p = cpy_a8; p = memcpy (p, s, 9); // { dg-warning "writing 9 bytes into a region of size 8" } sink (p); p = memcpy (p + 2, s, 7); // { dg-warning "writing 7 bytes into a region of size 6" } sink (p); p = memcpy (p + 3, s, 5); // { dg-warning "writing 5 bytes into a region of size 3" } sink (p); p = memcpy (p + 3, s, 3); // { dg-warning "writing 3 bytes into a region of size 0" } sink (p); } void nowarn_mempcpy (const void *s) { extern char a4[4]; unsigned n = sizeof a4; char *p = mempcpy (a4, s, n); sink (p); mempcpy (p - 4, s, n); sink (p); p = mempcpy (a4 + 1, s, n - 1); sink (p); mempcpy (p - 4, s, n); sink (p); p = mempcpy (a4 + 2, s, n - 2); sink (p); mempcpy (p - 4, s, n); sink (p); p = mempcpy (a4 + 3, s, n - 3); sink (p); mempcpy (p - 4, s, n); sink (p); p = mempcpy (a4 + 4, s, n - 4); sink (p); mempcpy (p - 4, s, n); sink (p); } void nowarn_mempcpy_chain (const void *s) { extern char pcpy_a8[8]; char *p = pcpy_a8; p = mempcpy (p + 1, s, 7); sink (p); p = mempcpy (p - 7 , s, 7); sink (p); p = mempcpy (p - 5 , s, 5); sink (p); p = mempcpy (p - 3 , s, 3); sink (p); p = mempcpy (p - 2 , s, 2); sink (p); mempcpy (p - 1, s, 1); sink (p); mempcpy (p - 8, s, 8); } void warn_mempcpy (const void *s) { extern char pcpy_a5[5]; // { dg-message "destination object 'pcpy_a5'" "note" } char *p = pcpy_a5; p = mempcpy (p, s, 5); sink (p); mempcpy (p - 5, s, 6); // { dg-warning "writing 6 bytes into a region of size 5 " } sink (p); p = pcpy_a5; p = mempcpy (p, s, 3); sink (p); mempcpy (p, s, 3); // { dg-warning "writing 3 bytes into a region of size 2 " } sink (p); p = pcpy_a5 + 1; p = mempcpy (p, s, 3); sink (p); mempcpy (p - 1, s, 5); // { dg-warning "writing 5 bytes into a region of size 2 " } sink (p); } void warn_mempcpy_chain_3 (const void *s) { char *p = malloc (5); // { dg-message "at offset \\\[3, 5] into destination object of size 5" "note" } p = mempcpy (p, s, UR (1, 2)); p = mempcpy (p, s, UR (2, 3)); p = mempcpy (p, s, UR (3, 4)); // { dg-warning "writing between 3 and 4 bytes into a region of size 2 " } sink (p); } void warn_mempcpy_offrng_chain_3 (const void *s) { char *p = malloc (11); // { dg-message "at offset \\\[9, 11] into destination object of size 11 " "note" } size_t r1_2 = UR (1, 2); size_t r2_3 = r1_2 + 1; size_t r3_4 = r2_3 + 1; p = mempcpy (p + r1_2, s, r1_2); p = mempcpy (p + r2_3, s, r2_3); p = mempcpy (p + r3_4, s, r3_4); // { dg-warning "writing between 3 and 4 bytes into a region of size 2 " } sink (p); } void warn_mempcpy_chain_4 (const void *s) { char *p = malloc (9); // { dg-message "at offset \\\[6, 9] into destination object of size 9 " "note" } p = mempcpy (p, s, UR (1, 2)); p = mempcpy (p, s, UR (2, 3)); p = mempcpy (p, s, UR (3, 4)); p = mempcpy (p, s, UR (4, 5)); // { dg-warning "writing between 4 and 5 bytes into a region of size 3 " } sink (p); } void warn_mempcpy_chain_5 (const void *s) { char *p = malloc (14); // { dg-message "at offset \\\[10, 14] into destination object of size 14 " "note" } p = mempcpy (p, s, UR (1, 2)); p = mempcpy (p, s, UR (2, 3)); p = mempcpy (p, s, UR (3, 4)); p = mempcpy (p, s, UR (4, 5)); p = mempcpy (p, s, UR (5, 6)); // { dg-warning "writing between 5 and 6 bytes into a region of size 4 " } sink (p); }