blob: e21452fdf24d27e5abf9aa59ac854232b2751242 [file] [log] [blame]
/* 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" }
}