1  /* { dg-do run } */
       2  /* { dg-skip-if "" { *-*-* } { "*" } { "-O2" } } */
       3  /* { dg-options "-fsanitize=undefined" } */
       4  
       5  /* Sanity-test -fsanitize=object-size.  We use -fsanitize=undefined option
       6     to check that this feature doesn't clash with -fsanitize=bounds et al.  */
       7  
       8  #define N 20
       9  
      10  __attribute__((noinline, noclone)) void
      11  f1 (int i)
      12  {
      13    volatile int j;
      14    char *p, *orig;
      15    orig = p = (char *) __builtin_calloc (N, 1);
      16    j = *(p + i);
      17    j = p[i];
      18    p++;
      19    j = p[i - 1];
      20    j = *(p + i - 1);
      21    __builtin_free (orig);
      22  }
      23  
      24  /* { dg-output "load of address \[^\n\r]* with insufficient space for an object of type 'char'\[^\n\r]*(\n|\r\n|\r)" } */
      25  /* { dg-output "\[^\n\r]*note: pointer points here\[^\n\r]*(\n|\r\n|\r)" } */
      26  /* { dg-output "\[^\n\r]*\[^\n\r]*(\n|\r\n|\r)" } */
      27  /* { dg-output "\[^\n\r]*\\^\[^\n\r]*(\n|\r\n|\r)" } */
      28  /* { dg-output "\[^\n\r]*load of address \[^\n\r]* with insufficient space for an object of type 'char'\[^\n\r]*(\n|\r\n|\r)" } */
      29  /* { dg-output "\[^\n\r]*note: pointer points here\[^\n\r]*(\n|\r\n|\r)" } */
      30  /* { dg-output "\[^\n\r]*\[^\n\r]*(\n|\r\n|\r)" } */
      31  /* { dg-output "\[^\n\r]*\\^\[^\n\r]*(\n|\r\n|\r)" } */
      32  /* { dg-output "\[^\n\r]*load of address \[^\n\r]* with insufficient space for an object of type 'char'\[^\n\r]*(\n|\r\n|\r)" } */
      33  /* { dg-output "\[^\n\r]*note: pointer points here\[^\n\r]*(\n|\r\n|\r)" } */
      34  /* { dg-output "\[^\n\r]*\[^\n\r]*(\n|\r\n|\r)" } */
      35  /* { dg-output "\[^\n\r]*\\^\[^\n\r]*(\n|\r\n|\r)" } */
      36  /* { dg-output "\[^\n\r]*load of address \[^\n\r]* with insufficient space for an object of type 'char'\[^\n\r]*(\n|\r\n|\r)" } */
      37  /* { dg-output "\[^\n\r]*note: pointer points here\[^\n\r]*(\n|\r\n|\r)" } */
      38  /* { dg-output "\[^\n\r]*\[^\n\r]*(\n|\r\n|\r)" } */
      39  /* { dg-output "\[^\n\r]*\\^\[^\n\r]*(\n|\r\n|\r)" } */
      40  
      41  __attribute__((noinline, noclone)) void
      42  f2 (int i)
      43  {
      44    volatile int j;
      45    char a[N];
      46    __builtin_memset (a, 0, N);
      47    j = *(a + i);
      48    char *p = a;
      49    j = *(p + i);
      50    j = p[i];
      51    p += 10;
      52    j = *(p + i - 10);
      53    j = p[i - 10];
      54  }
      55  
      56  /* { dg-output "\[^\n\r]*load of address \[^\n\r]* with insufficient space for an object of type 'char'\[^\n\r]*(\n|\r\n|\r)" } */
      57  /* { dg-output "\[^\n\r]*note: pointer points here\[^\n\r]*(\n|\r\n|\r)" } */
      58  /* { dg-output "\[^\n\r]*\[^\n\r]*(\n|\r\n|\r)" } */
      59  /* { dg-output "\[^\n\r]*\\^\[^\n\r]*(\n|\r\n|\r)" } */
      60  /* { dg-output "\[^\n\r]*load of address \[^\n\r]* with insufficient space for an object of type 'char'\[^\n\r]*(\n|\r\n|\r)" } */
      61  /* { dg-output "\[^\n\r]*note: pointer points here\[^\n\r]*(\n|\r\n|\r)" } */
      62  /* { dg-output "\[^\n\r]*\[^\n\r]*(\n|\r\n|\r)" } */
      63  /* { dg-output "\[^\n\r]*\\^\[^\n\r]*(\n|\r\n|\r)" } */
      64  /* { dg-output "\[^\n\r]*load of address \[^\n\r]* with insufficient space for an object of type 'char'\[^\n\r]*(\n|\r\n|\r)" } */
      65  /* { dg-output "\[^\n\r]*note: pointer points here\[^\n\r]*(\n|\r\n|\r)" } */
      66  /* { dg-output "\[^\n\r]*\[^\n\r]*(\n|\r\n|\r)" } */
      67  /* { dg-output "\[^\n\r]*\\^\[^\n\r]*(\n|\r\n|\r)" } */
      68  /* { dg-output "\[^\n\r]*load of address \[^\n\r]* with insufficient space for an object of type 'char'\[^\n\r]*(\n|\r\n|\r)" } */
      69  /* { dg-output "\[^\n\r]*note: pointer points here\[^\n\r]*(\n|\r\n|\r)" } */
      70  /* { dg-output "\[^\n\r]*\[^\n\r]*(\n|\r\n|\r)" } */
      71  /* { dg-output "\[^\n\r]*\\^\[^\n\r]*(\n|\r\n|\r)" } */
      72  
      73  __attribute__((noinline, noclone)) void
      74  f3 (int i)
      75  {
      76    volatile int j;
      77    int *p = (int *) __builtin_calloc (N, sizeof (*p));
      78    int *o = &p[i];
      79    j = *o;
      80    j = o[0];
      81    __builtin_free (p);
      82  }
      83  
      84  /* { dg-output "\[^\n\r]*load of address \[^\n\r]* with insufficient space for an object of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
      85  /* { dg-output "\[^\n\r]*note: pointer points here\[^\n\r]*(\n|\r\n|\r)" } */
      86  /* { dg-output "\[^\n\r]*\[^\n\r]*(\n|\r\n|\r)" } */
      87  /* { dg-output "\[^\n\r]*\\^\[^\n\r]*(\n|\r\n|\r)" } */
      88  /* { dg-output "\[^\n\r]*load of address \[^\n\r]* with insufficient space for an object of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
      89  /* { dg-output "\[^\n\r]*note: pointer points here\[^\n\r]*(\n|\r\n|\r)" } */
      90  /* { dg-output "\[^\n\r]*\[^\n\r]*(\n|\r\n|\r)" } */
      91  /* { dg-output "\[^\n\r]*\\^\[^\n\r]*(\n|\r\n|\r)" } */
      92  
      93  __attribute__((noinline, noclone)) void
      94  f4 (void)
      95  {
      96    /* The second argument to __builtin_calloc is intentional.  */
      97    int *p = (int *) __builtin_calloc (3, 1);
      98    *p = 42;
      99    __builtin_free (p);
     100  }
     101  
     102  /* { dg-output "\[^\n\r]*store to address \[^\n\r]* with insufficient space for an object of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
     103  /* { dg-output "\[^\n\r]*note: pointer points here\[^\n\r]*(\n|\r\n|\r)" } */
     104  /* { dg-output "\[^\n\r]*\[^\n\r]*(\n|\r\n|\r)" } */
     105  /* { dg-output "\[^\n\r]*\\^" } */
     106  
     107  __attribute__((noinline, noclone)) void
     108  f5 (int *p)
     109  {
     110    /* This is not instrumented.  But don't ICE, etc.  */
     111    volatile int i = p[N];
     112  }
     113  
     114  int
     115  main ()
     116  {
     117    f1 (N);
     118    f2 (N);
     119    f3 (N);
     120    f4 ();
     121    int *p = (int *) __builtin_calloc (N, sizeof (*p));
     122    f5 (p);
     123    __builtin_free (p);
     124    return 0;
     125  }