| /* PR middle-end/91631 - buffer overflow into an array member of a declared |
| object not detected |
| Test to verify that past-the-end accesses by string functions to member |
| arrays by-reference objects are diagnosed. |
| { dg-do compile } |
| { dg-options "-O2 -Wall -Wno-unused-local-typedefs -ftrack-macro-expansion=0" } */ |
| |
| extern char* strcpy (char*, const char*); |
| extern char* strcat (char*, const char*); |
| |
| void sink (void*, ...); |
| |
| #define S36 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" |
| |
| #define S(N) (S36 + sizeof (S36) - N - 1) |
| |
| /* In the test macro, prevent the strcpy to memcpy transformation |
| by using a local array initialized with the string literal. Without |
| it, GCC transforms the strcpy call with memcpy which (unfortunately) |
| permits accesses that cross subobject boundaries. */ |
| #define T(dst, ncpy, ncat) \ |
| do { \ |
| const char a[] = S36; \ |
| strcpy (dst, a + sizeof a - ncpy - 1); \ |
| const char b[] = S36; \ |
| strcat (dst, b + sizeof b - ncat - 1); \ |
| sink (dst); \ |
| } while (0) |
| |
| |
| struct MemArrays |
| { |
| char a7[7]; // { dg-message "'a7' declared here" } |
| char a4[4]; // { dg-message "'a4' declared here" } |
| char a3[3]; // { dg-message "'a3' declared here" } |
| }; |
| |
| struct MemArrays gma; |
| |
| void strcat_value (void) |
| { |
| T (gma.a7, 1, 1); |
| T (gma.a7, 1, 5); |
| T (gma.a7, 1, 6); // { dg-warning "'strcat' offset 7 from the object at 'gma' is out of the bounds of referenced subobject 'a7' with type 'char\\\[7]' at offset 0" } |
| T (gma.a7, 1, 7); // { dg-warning "'strcat' offset \\\[7, 8] from the object at 'gma' is out of the bounds of referenced subobject 'a7' with type 'char\\\[7]' at offset 0" } |
| |
| T (gma.a7, 2, 1); |
| T (gma.a7, 2, 4); |
| T (gma.a7, 2, 5); // { dg-warning "'strcat' offset 7 from the object at 'gma' is out of the bounds of referenced subobject 'a7' with type 'char\\\[7]' at offset 0" } |
| T (gma.a7, 2, 6); // { dg-warning "'strcat' offset \\\[7, 8] from the object at 'gma' is out of the bounds of referenced subobject 'a7' with type 'char\\\[7]' at offset 0" } |
| |
| T (gma.a7, 5, 1); |
| T (gma.a7, 5, 2); // { dg-warning "'strcat' offset 7 from the object at 'gma' is out of the bounds of referenced subobject 'a7' with type 'char\\\[7]' at offset 0" } |
| |
| T (gma.a4, 1, 1); |
| T (gma.a4, 1, 2); |
| T (gma.a4, 1, 3); // { dg-warning "'strcat' offset 11 from the object at 'gma' is out of the bounds of referenced subobject 'a4' with type 'char\\\[4]' at offset 7" } |
| T (gma.a4, 1, 4); // { dg-warning "'strcat' offset \\\[11, 12] from the object at 'gma' is out of the bounds of referenced subobject 'a4' with type 'char\\\[4]' at offset 7" } |
| |
| T (gma.a4, 2, 3); // { dg-warning "'strcat' offset \\\[11, 12] from the object at 'gma' is out of the bounds of referenced subobject 'a4' with type 'char\\\[4]' at offset 7" } |
| |
| T (gma.a3, 1, 1); |
| T (gma.a3, 1, 2); // { dg-warning "'strcat' offset 14 from the object at 'gma' is out of the bounds of referenced subobject 'a3' with type 'char\\\[3]' at offset 11" } |
| } |
| |
| |
| void strcat_ref (struct MemArrays *pma) |
| { |
| T (pma->a7, 1, 1); |
| T (pma->a7, 1, 5); |
| T (pma->a7, 1, 6); // { dg-warning "'strcat' offset 7 from the object at 'pma' is out of the bounds of referenced subobject 'a7' with type 'char\\\[7]' at offset 0" } |
| T (pma->a7, 1, 7); // { dg-warning "'strcat' offset \\\[7, 8] from the object at 'pma' is out of the bounds of referenced subobject 'a7' with type 'char\\\[7]' at offset 0" } |
| |
| T (pma->a7, 2, 1); |
| T (pma->a7, 2, 4); |
| T (pma->a7, 2, 5); // { dg-warning "'strcat' offset 7 from the object at 'pma' is out of the bounds of referenced subobject 'a7' with type 'char\\\[7]' at offset 0" } |
| T (pma->a7, 2, 6); // { dg-warning "'strcat' offset \\\[7, 8] from the object at 'pma' is out of the bounds of referenced subobject 'a7' with type 'char\\\[7]' at offset 0" } |
| |
| T (pma->a4, 1, 1); |
| T (pma->a4, 1, 2); |
| T (pma->a4, 1, 3); // { dg-warning "'strcat' offset 11 from the object at 'pma' is out of the bounds of referenced subobject 'a4' with type 'char\\\[4]' at offset 7" } |
| T (pma->a4, 1, 4); // { dg-warning "'strcat' offset \\\[11, 12] from the object at 'pma' is out of the bounds of referenced subobject 'a4' with type 'char\\\[4]' at offset 7" } |
| |
| T (pma->a4, 2, 3); // { dg-warning "'strcat' offset \\\[11, 12] from the object at 'pma' is out of the bounds of referenced subobject 'a4' with type 'char\\\[4]' at offset 7" } |
| |
| T (pma->a3, 1, 1); |
| T (pma->a3, 1, 2); // { dg-warning "'strcat' offset 14 from the object at 'pma' is out of the bounds of referenced subobject 'a3' with type 'char\\\[3]' at offset 11" } |
| } |
| |
| |
| #define T2(dst1, dst2, ncpy, ncat) \ |
| do { \ |
| const char a[] = S36; \ |
| strcpy (dst1, a + sizeof a - ncpy - 1); \ |
| const char b[] = S36; \ |
| strcat (dst2, b + sizeof b - ncat - 1); \ |
| sink (dst1, dst2); \ |
| } while (0) |
| |
| struct ArraysOfMemArrays |
| { |
| struct MemArrays ma3[3]; |
| } a3[3]; |
| |
| void strcat_arrays_of_arrays_value (void) |
| { |
| T2 (a3[0].ma3[0].a7, a3[0].ma3[0].a7, 6, 6); // { dg-warning "\\\[-Warray-bounds" } |
| T2 (a3[0].ma3[0].a7, a3[0].ma3[1].a7, 6, 6); |
| T2 (a3[0].ma3[0].a7, a3[0].ma3[2].a7, 6, 6); |
| |
| T2 (a3[0].ma3[1].a7, a3[0].ma3[0].a7, 6, 6); |
| T2 (a3[0].ma3[1].a7, a3[0].ma3[1].a7, 6, 6); // { dg-warning "\\\[-Warray-bounds" } |
| T2 (a3[0].ma3[1].a7, a3[0].ma3[2].a7, 6, 6); |
| |
| T2 (a3[0].ma3[2].a7, a3[0].ma3[0].a7, 6, 6); |
| T2 (a3[0].ma3[2].a7, a3[0].ma3[1].a7, 6, 6); |
| T2 (a3[0].ma3[2].a7, a3[0].ma3[2].a7, 6, 6); // { dg-warning "\\\[-Warray-bounds" } |
| |
| T2 (a3[0].ma3[0].a7, a3[1].ma3[0].a7, 6, 6); |
| T2 (a3[0].ma3[0].a7, a3[1].ma3[1].a7, 6, 6); |
| T2 (a3[0].ma3[0].a7, a3[1].ma3[2].a7, 6, 6); |
| |
| T2 (a3[0].ma3[1].a7, a3[1].ma3[0].a7, 6, 6); |
| T2 (a3[0].ma3[1].a7, a3[1].ma3[1].a7, 6, 6); |
| T2 (a3[0].ma3[1].a7, a3[1].ma3[2].a7, 6, 6); |
| |
| T2 (a3[0].ma3[2].a7, a3[1].ma3[0].a7, 6, 6); |
| T2 (a3[0].ma3[2].a7, a3[1].ma3[1].a7, 6, 6); |
| T2 (a3[0].ma3[2].a7, a3[1].ma3[2].a7, 6, 6); |
| |
| T2 (a3[0].ma3[0].a7, a3[2].ma3[0].a7, 6, 6); |
| T2 (a3[0].ma3[0].a7, a3[2].ma3[1].a7, 6, 6); |
| T2 (a3[0].ma3[0].a7, a3[2].ma3[2].a7, 6, 6); |
| |
| T2 (a3[0].ma3[1].a7, a3[2].ma3[0].a7, 6, 6); |
| T2 (a3[0].ma3[1].a7, a3[2].ma3[1].a7, 6, 6); |
| T2 (a3[0].ma3[1].a7, a3[2].ma3[2].a7, 6, 6); |
| |
| T2 (a3[0].ma3[2].a7, a3[2].ma3[0].a7, 6, 6); |
| T2 (a3[0].ma3[2].a7, a3[2].ma3[1].a7, 6, 6); |
| T2 (a3[0].ma3[2].a7, a3[2].ma3[2].a7, 6, 6); |
| |
| |
| T2 (a3[1].ma3[0].a7, a3[0].ma3[0].a7, 6, 6); |
| T2 (a3[1].ma3[0].a7, a3[0].ma3[1].a7, 6, 6); |
| T2 (a3[1].ma3[0].a7, a3[0].ma3[2].a7, 6, 6); |
| |
| T2 (a3[1].ma3[1].a7, a3[0].ma3[0].a7, 6, 6); |
| T2 (a3[1].ma3[1].a7, a3[0].ma3[1].a7, 6, 6); |
| T2 (a3[1].ma3[1].a7, a3[0].ma3[2].a7, 6, 6); |
| |
| T2 (a3[1].ma3[2].a7, a3[0].ma3[0].a7, 6, 6); |
| T2 (a3[1].ma3[2].a7, a3[0].ma3[1].a7, 6, 6); |
| T2 (a3[1].ma3[2].a7, a3[0].ma3[2].a7, 6, 6); |
| |
| T2 (a3[1].ma3[0].a7, a3[1].ma3[0].a7, 6, 6); // { dg-warning "\\\[-Warray-bounds" } |
| T2 (a3[1].ma3[0].a7, a3[1].ma3[1].a7, 6, 6); |
| T2 (a3[1].ma3[0].a7, a3[1].ma3[2].a7, 6, 6); |
| |
| T2 (a3[1].ma3[1].a7, a3[1].ma3[0].a7, 6, 6); |
| T2 (a3[1].ma3[1].a7, a3[1].ma3[1].a7, 6, 6); // { dg-warning "\\\[-Warray-bounds" } |
| T2 (a3[1].ma3[1].a7, a3[1].ma3[2].a7, 6, 6); |
| |
| T2 (a3[1].ma3[2].a7, a3[1].ma3[0].a7, 6, 6); |
| T2 (a3[1].ma3[2].a7, a3[1].ma3[1].a7, 6, 6); |
| T2 (a3[1].ma3[2].a7, a3[1].ma3[2].a7, 6, 6); // { dg-warning "\\\[-Warray-bounds" } |
| |
| T2 (a3[1].ma3[0].a7, a3[2].ma3[0].a7, 6, 6); |
| T2 (a3[1].ma3[0].a7, a3[2].ma3[1].a7, 6, 6); |
| T2 (a3[1].ma3[0].a7, a3[2].ma3[2].a7, 6, 6); |
| |
| T2 (a3[1].ma3[1].a7, a3[2].ma3[0].a7, 6, 6); |
| T2 (a3[1].ma3[1].a7, a3[2].ma3[1].a7, 6, 6); |
| T2 (a3[1].ma3[1].a7, a3[2].ma3[2].a7, 6, 6); |
| |
| T2 (a3[1].ma3[2].a7, a3[2].ma3[0].a7, 6, 6); |
| T2 (a3[1].ma3[2].a7, a3[2].ma3[1].a7, 6, 6); |
| T2 (a3[1].ma3[2].a7, a3[2].ma3[2].a7, 6, 6); |
| |
| |
| T2 (a3[2].ma3[0].a7, a3[0].ma3[0].a7, 6, 6); |
| T2 (a3[2].ma3[0].a7, a3[0].ma3[1].a7, 6, 6); |
| T2 (a3[2].ma3[0].a7, a3[0].ma3[2].a7, 6, 6); |
| |
| T2 (a3[2].ma3[1].a7, a3[0].ma3[0].a7, 6, 6); |
| T2 (a3[2].ma3[1].a7, a3[0].ma3[1].a7, 6, 6); |
| T2 (a3[2].ma3[1].a7, a3[0].ma3[2].a7, 6, 6); |
| |
| T2 (a3[2].ma3[2].a7, a3[0].ma3[0].a7, 6, 6); |
| T2 (a3[2].ma3[2].a7, a3[0].ma3[1].a7, 6, 6); |
| T2 (a3[2].ma3[2].a7, a3[0].ma3[2].a7, 6, 6); |
| |
| T2 (a3[2].ma3[0].a7, a3[1].ma3[0].a7, 6, 6); |
| T2 (a3[2].ma3[0].a7, a3[1].ma3[1].a7, 6, 6); |
| T2 (a3[2].ma3[0].a7, a3[1].ma3[2].a7, 6, 6); |
| |
| T2 (a3[2].ma3[1].a7, a3[1].ma3[0].a7, 6, 6); |
| T2 (a3[2].ma3[1].a7, a3[1].ma3[1].a7, 6, 6); |
| T2 (a3[2].ma3[1].a7, a3[1].ma3[2].a7, 6, 6); |
| |
| T2 (a3[2].ma3[2].a7, a3[1].ma3[0].a7, 6, 6); |
| T2 (a3[2].ma3[2].a7, a3[1].ma3[1].a7, 6, 6); |
| T2 (a3[2].ma3[2].a7, a3[1].ma3[2].a7, 6, 6); |
| |
| T2 (a3[2].ma3[0].a7, a3[2].ma3[0].a7, 6, 6); // { dg-warning "\\\[-Warray-bounds" } |
| T2 (a3[2].ma3[0].a7, a3[2].ma3[1].a7, 6, 6); |
| T2 (a3[2].ma3[0].a7, a3[2].ma3[2].a7, 6, 6); |
| |
| T2 (a3[2].ma3[1].a7, a3[2].ma3[0].a7, 6, 6); |
| T2 (a3[2].ma3[1].a7, a3[2].ma3[1].a7, 6, 6); // { dg-warning "\\\[-Warray-bounds" } |
| T2 (a3[2].ma3[1].a7, a3[2].ma3[2].a7, 6, 6); |
| |
| T2 (a3[2].ma3[2].a7, a3[2].ma3[0].a7, 6, 6); |
| T2 (a3[2].ma3[2].a7, a3[2].ma3[1].a7, 6, 6); |
| T2 (a3[2].ma3[2].a7, a3[2].ma3[2].a7, 6, 6); // { dg-warning "\\\[-Warray-bounds" } |
| } |
| |
| |
| void strcat_arrays_of_arrays_ref (struct ArraysOfMemArrays *p) |
| { |
| T2 (p[0].ma3[0].a7, p[0].ma3[0].a7, 6, 6); // { dg-warning "\\\[-Warray-bounds" } |
| T2 (p[0].ma3[0].a7, p[0].ma3[1].a7, 6, 6); |
| T2 (p[0].ma3[0].a7, p[0].ma3[2].a7, 6, 6); |
| |
| T2 (p[0].ma3[1].a7, p[0].ma3[0].a7, 6, 6); |
| T2 (p[0].ma3[1].a7, p[0].ma3[1].a7, 6, 6); // { dg-warning "\\\[-Warray-bounds" } |
| T2 (p[0].ma3[1].a7, p[0].ma3[2].a7, 6, 6); |
| |
| T2 (p[0].ma3[2].a7, p[0].ma3[0].a7, 6, 6); |
| T2 (p[0].ma3[2].a7, p[0].ma3[1].a7, 6, 6); |
| T2 (p[0].ma3[2].a7, p[0].ma3[2].a7, 6, 6); // { dg-warning "\\\[-Warray-bounds" } |
| |
| T2 (p[0].ma3[0].a7, p[1].ma3[0].a7, 6, 6); |
| T2 (p[0].ma3[0].a7, p[1].ma3[1].a7, 6, 6); |
| T2 (p[0].ma3[0].a7, p[1].ma3[2].a7, 6, 6); |
| |
| T2 (p[0].ma3[1].a7, p[1].ma3[0].a7, 6, 6); |
| T2 (p[0].ma3[1].a7, p[1].ma3[1].a7, 6, 6); |
| T2 (p[0].ma3[1].a7, p[1].ma3[2].a7, 6, 6); |
| |
| T2 (p[0].ma3[2].a7, p[1].ma3[0].a7, 6, 6); |
| T2 (p[0].ma3[2].a7, p[1].ma3[1].a7, 6, 6); |
| T2 (p[0].ma3[2].a7, p[1].ma3[2].a7, 6, 6); |
| |
| T2 (p[0].ma3[0].a7, p[2].ma3[0].a7, 6, 6); |
| T2 (p[0].ma3[0].a7, p[2].ma3[1].a7, 6, 6); |
| T2 (p[0].ma3[0].a7, p[2].ma3[2].a7, 6, 6); |
| |
| T2 (p[0].ma3[1].a7, p[2].ma3[0].a7, 6, 6); |
| T2 (p[0].ma3[1].a7, p[2].ma3[1].a7, 6, 6); |
| T2 (p[0].ma3[1].a7, p[2].ma3[2].a7, 6, 6); |
| |
| T2 (p[0].ma3[2].a7, p[2].ma3[0].a7, 6, 6); |
| T2 (p[0].ma3[2].a7, p[2].ma3[1].a7, 6, 6); |
| T2 (p[0].ma3[2].a7, p[2].ma3[2].a7, 6, 6); |
| |
| |
| T2 (p[1].ma3[0].a7, p[0].ma3[0].a7, 6, 6); |
| T2 (p[1].ma3[0].a7, p[0].ma3[1].a7, 6, 6); |
| T2 (p[1].ma3[0].a7, p[0].ma3[2].a7, 6, 6); |
| |
| T2 (p[1].ma3[1].a7, p[0].ma3[0].a7, 6, 6); |
| T2 (p[1].ma3[1].a7, p[0].ma3[1].a7, 6, 6); |
| T2 (p[1].ma3[1].a7, p[0].ma3[2].a7, 6, 6); |
| |
| T2 (p[1].ma3[2].a7, p[0].ma3[0].a7, 6, 6); |
| T2 (p[1].ma3[2].a7, p[0].ma3[1].a7, 6, 6); |
| T2 (p[1].ma3[2].a7, p[0].ma3[2].a7, 6, 6); |
| |
| T2 (p[1].ma3[0].a7, p[1].ma3[0].a7, 6, 6); // { dg-warning "\\\[-Warray-bounds" } |
| T2 (p[1].ma3[0].a7, p[1].ma3[1].a7, 6, 6); |
| T2 (p[1].ma3[0].a7, p[1].ma3[2].a7, 6, 6); |
| |
| T2 (p[1].ma3[1].a7, p[1].ma3[0].a7, 6, 6); |
| T2 (p[1].ma3[1].a7, p[1].ma3[1].a7, 6, 6); // { dg-warning "\\\[-Warray-bounds" } |
| T2 (p[1].ma3[1].a7, p[1].ma3[2].a7, 6, 6); |
| |
| T2 (p[1].ma3[2].a7, p[1].ma3[0].a7, 6, 6); |
| T2 (p[1].ma3[2].a7, p[1].ma3[1].a7, 6, 6); |
| T2 (p[1].ma3[2].a7, p[1].ma3[2].a7, 6, 6); // { dg-warning "\\\[-Warray-bounds" } |
| |
| T2 (p[1].ma3[0].a7, p[2].ma3[0].a7, 6, 6); |
| T2 (p[1].ma3[0].a7, p[2].ma3[1].a7, 6, 6); |
| T2 (p[1].ma3[0].a7, p[2].ma3[2].a7, 6, 6); |
| |
| T2 (p[1].ma3[1].a7, p[2].ma3[0].a7, 6, 6); |
| T2 (p[1].ma3[1].a7, p[2].ma3[1].a7, 6, 6); |
| T2 (p[1].ma3[1].a7, p[2].ma3[2].a7, 6, 6); |
| |
| T2 (p[1].ma3[2].a7, p[2].ma3[0].a7, 6, 6); |
| T2 (p[1].ma3[2].a7, p[2].ma3[1].a7, 6, 6); |
| T2 (p[1].ma3[2].a7, p[2].ma3[2].a7, 6, 6); |
| |
| |
| T2 (p[2].ma3[0].a7, p[0].ma3[0].a7, 6, 6); |
| T2 (p[2].ma3[0].a7, p[0].ma3[1].a7, 6, 6); |
| T2 (p[2].ma3[0].a7, p[0].ma3[2].a7, 6, 6); |
| |
| T2 (p[2].ma3[1].a7, p[0].ma3[0].a7, 6, 6); |
| T2 (p[2].ma3[1].a7, p[0].ma3[1].a7, 6, 6); |
| T2 (p[2].ma3[1].a7, p[0].ma3[2].a7, 6, 6); |
| |
| T2 (p[2].ma3[2].a7, p[0].ma3[0].a7, 6, 6); |
| T2 (p[2].ma3[2].a7, p[0].ma3[1].a7, 6, 6); |
| T2 (p[2].ma3[2].a7, p[0].ma3[2].a7, 6, 6); |
| |
| T2 (p[2].ma3[0].a7, p[1].ma3[0].a7, 6, 6); |
| T2 (p[2].ma3[0].a7, p[1].ma3[1].a7, 6, 6); |
| T2 (p[2].ma3[0].a7, p[1].ma3[2].a7, 6, 6); |
| |
| T2 (p[2].ma3[1].a7, p[1].ma3[0].a7, 6, 6); |
| T2 (p[2].ma3[1].a7, p[1].ma3[1].a7, 6, 6); |
| T2 (p[2].ma3[1].a7, p[1].ma3[2].a7, 6, 6); |
| |
| T2 (p[2].ma3[2].a7, p[1].ma3[0].a7, 6, 6); |
| T2 (p[2].ma3[2].a7, p[1].ma3[1].a7, 6, 6); |
| T2 (p[2].ma3[2].a7, p[1].ma3[2].a7, 6, 6); |
| |
| T2 (p[2].ma3[0].a7, p[2].ma3[0].a7, 6, 6); // { dg-warning "\\\[-Warray-bounds" } |
| T2 (p[2].ma3[0].a7, p[2].ma3[1].a7, 6, 6); |
| T2 (p[2].ma3[0].a7, p[2].ma3[2].a7, 6, 6); |
| |
| T2 (p[2].ma3[1].a7, p[2].ma3[0].a7, 6, 6); |
| T2 (p[2].ma3[1].a7, p[2].ma3[1].a7, 6, 6); // { dg-warning "\\\[-Warray-bounds" } |
| T2 (p[2].ma3[1].a7, p[2].ma3[2].a7, 6, 6); |
| |
| T2 (p[2].ma3[2].a7, p[2].ma3[0].a7, 6, 6); |
| T2 (p[2].ma3[2].a7, p[2].ma3[1].a7, 6, 6); |
| T2 (p[2].ma3[2].a7, p[2].ma3[2].a7, 6, 6); // { dg-warning "\\\[-Warray-bounds" } |
| } |