view gcc/testsuite/gcc.dg/Warray-bounds-45.c @ 145:1830386684a0

gcc-9.2.0
author anatofuz
date Thu, 13 Feb 2020 11:34:05 +0900
parents
children
line wrap: on
line source

/* 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" }
}