1  /* Verify that calls to strnlen with an unterminated array and
       2     an excessive non-constant bound are diagnosed.
       3     { dg-do compile }
       4     { dg-options "-O2 -Wall -ftrack-macro-expansion=0" } */
       5  
       6  #include "range.h"
       7  
       8  extern size_t strnlen (const char*, size_t);
       9  
      10  const char a[5] = "12345";   /* { dg-message "declared here" } */
      11  enum { asz = sizeof a };
      12  
      13  int v0 = 0;
      14  int v1 = 1;
      15  
      16  void sink (int, ...);
      17  
      18  #define CONCAT(a, b)   a ## b
      19  #define CAT(a, b)      CONCAT(a, b)
      20  
      21  #define T(str, n)					\
      22    __attribute__ ((noipa))				\
      23    void CAT (test_, __LINE__) (void) {			\
      24      int i0 = 0, i1 = i0 + 1, i2 = i1 + 1, i3 = i2 + 1;	\
      25      sink (strnlen (str, n), i0, i1, i2, i3);		\
      26    } typedef void dummy_type
      27  
      28  
      29  T (a, UR (asz, -1));
      30  T (a, UR (asz - 1, -1));
      31  T (a, UR (asz - 2, -1));
      32  T (a, UR (asz - 5, -1));
      33  T (&a[0], UR (asz, -1));
      34  T (&a[0] + 1, UR (asz, asz + 1)); /* { dg-warning "specified bound \\\[5, 6] exceeds the size 4 of unterminated array" } */
      35  T (&a[1], UR (asz, 6));           /* { dg-warning "specified bound \\\[5, 6] exceeds the size 4 of unterminated array" } */
      36  T (&a[1], UR (asz - 1, 7));
      37  T (&a[v0], UR (asz, 8));          /* { dg-warning "specified bound \\\[5, 8] may exceed the size of at most 5 of unterminated array" } */
      38  T (&a[v0] + 1, UR (asz, 9));      /* { dg-warning "specified bound \\\[5, 9] may exceed the size of at most 5 of unterminated array" } */
      39  
      40  T (a, UR (asz + 1, asz + 2));     /* { dg-warning "specified bound \\\[6, 7] exceeds the size 5 " } */
      41  T (&a[0], UR (asz + 1, 10));      /* { dg-warning "unterminated" } */
      42  T (&a[0] + 1, UR (asz - 1, 11));
      43  T (&a[0] + 1, UR (asz + 1, 12));  /* { dg-warning "unterminated" } */
      44  T (&a[1], UR (asz + 1, 13));      /* { dg-warning "unterminated" } */
      45  T (&a[v0], UR (asz + 1, 14));     /* { dg-warning "unterminated" } */
      46  T (&a[v0] + 1, UR (asz + 1, 15)); /* { dg-warning "unterminated" } */
      47  
      48  T (&a[v0] + 1, UR (DIFF_MAX, SIZE_MAX)); /* { dg-warning "unterminated" } */
      49  
      50  T (&a[v0] + 1, UR (DIFF_MAX + (size_t)1, SIZE_MAX)); /* { dg-warning "specified bound \\\[\[0-9\]+, \[0-9\]+] exceeds maximum object size " } */
      51  
      52  
      53  const char c[4] = "1234";
      54  
      55  void test (int n0)
      56  {
      57    char a[] = "123";
      58  
      59    if (n0 < 4)
      60      n0 = 4;
      61    int n1 = __builtin_strlen (a);
      62  
      63    int n = n0 < n1 ? n1 : n0;
      64  
      65    /* N is at least 4 and c[4] is out-of-bounds.  This could trigger
      66       either -Warray-bounds or -Wstringop-overread.  -Warray-bounds
      67       only diagnoses past-the-end accesses by modifying functions
      68       (in gimple-ssa-warn-restrict.c) and even for those, either
      69       -Wstringop-overflow or -Wstringop-overread would be more
      70       appropriate.  */
      71    sink (strnlen (c + n, n + 1));    /* { dg-warning "specified bound \\\[5, \[0-9\]+] exceeds the size of at most 4 of unterminated array" } */
      72  }