(root)/
gcc-13.2.0/
gcc/
testsuite/
c-c++-common/
Wstringop-overflow.c
       1  /* PR middle-end/81117 - Improve buffer overflow checking in strncpy
       2     { dg-do compile }
       3     { dg-options "-O2 -Wstringop-overflow -Wno-stringop-truncation -ftrack-macro-expansion=0" } */
       4  
       5  typedef __SIZE_TYPE__ size_t;
       6  
       7  #if __cplusplus
       8  extern "C" {
       9  #endif
      10  
      11  size_t strlen (const char*);
      12  char* strncat (char*, const char*, size_t);
      13  char* strncpy (char*, const char*, size_t);
      14  #if __cplusplus
      15  }
      16  #endif
      17  
      18  const char ar[] = "123";
      19  
      20  void test_strncat (char **d, const char* s, int i)
      21  {
      22    /* Use a fresh pointer for each test to prevent the optimizer from
      23       eliminating redundant writes into the same destination.  Avoid
      24       calling functions like sink() on the result that would have to
      25       be assumed to change the source string by the alias oracle.  */
      26  #define T(d, s, len) strncat (*d++, (s), (len))
      27  
      28    T (d, "",    0);
      29    T (d, "",    1);
      30    T (d, "",    2);
      31    T (d, "",    3);
      32    T (d, "123", 0);
      33    /* The following two calls truncate the copy and are diagnosed
      34       by -Wstringop-truncation but there is evidence of overflow so
      35       they're not diagnosed by -Wstringop-overflow.  */
      36    T (d, "123", 1);
      37    T (d, "123", 2);
      38  
      39    T (d, "123", 3);                /* { dg-warning ".strncat\[^\n\r\]* specified bound 3 equals source length" } */
      40    T (d, "123", 4);
      41    T (d, "123", 9);
      42  
      43    T (d, s, strlen (s));           /* { dg-warning ".strncat\[^\n\r\]* specified bound depends on the length of the source argument" } */
      44    T (d, s, strlen (s) + 1);       /* { dg-warning ".strncat\[^\n\r\]* specified bound depends on the length of the source argument" } */
      45    /* The following could also be diagnosed by -Wstringop-truncation
      46       (with some effort to distinguish the pattern from others like
      47       the one above.  */
      48    T (d, s, strlen (s) - 1);       /* { dg-warning ".strncat\[^\n\r\]* specified bound depends on the length of the source argument" } */
      49    T (d, s, strlen (s) - i);       /* { dg-warning ".strncat\[^\n\r\]* specified bound depends on the length of the source argument" } */
      50  
      51    /* The following is dubious but not necessarily a smoking gun.  */
      52    T (d, s, strlen (s) - strlen (s));
      53  
      54    {
      55      signed char n = strlen (s);   /* { dg-message "length computed here" } */
      56      T (d, s, n);                  /* { dg-warning ".strncat\[^\n\r\]* specified bound depends on the length of the source argument" } */
      57    }
      58  
      59    {
      60      short n = strlen (s);         /* { dg-message "length computed here" } */
      61      T (d, s, n);                  /* { dg-warning ".strncat\[^\n\r\]* specified bound depends on the length of the source argument" } */
      62    }
      63  
      64    {
      65      int n = strlen (s);           /* { dg-message "length computed here" } */
      66      T (d, s, n);                  /* { dg-warning ".strncat\[^\n\r\]* specified bound depends on the length of the source argument" } */
      67    }
      68  
      69    {
      70      unsigned n = strlen (s);      /* { dg-message "length computed here" } */
      71      T (d, s, n);                  /* { dg-warning ".strncat\[^\n\r\]* specified bound depends on the length of the source argument" } */
      72    }
      73  
      74    {
      75      size_t n;
      76      n = strlen (s);               /* { dg-message "length computed here" } */
      77      T (d, s, n);                  /* { dg-warning ".strncat\[^\n\r\]* specified bound depends on the length of the source argument" } */
      78    }
      79  
      80    {
      81      size_t n;
      82      n = strlen (s) - 1;           /* { dg-message "length computed here" } */
      83      T (d, s, n);                  /* { dg-message ".strncat\[^\n\r\]* specified bound depends on the length of the source argument" } */
      84    }
      85  
      86    {
      87      /* This doesn't overflow so iit should not be diagnosed.  */
      88      size_t n = strlen (s) - strlen (s);
      89      T (d, s, n);
      90    }
      91  
      92    {
      93      size_t n = i < strlen (s) ? i : strlen (s);   /* { dg-message "length computed here" } */
      94      T (d, s, n);                  /* { dg-message ".strncat\[^\n\r\]* specified bound depends on the length of the source argument" } */
      95    }
      96  }
      97  
      98  
      99  void test_strncpy (char **d, const char* s, int i)
     100  {
     101  #undef T
     102  #define T(d, s, len) strncpy (*d++, (s), (len))
     103  
     104    T (d, "",    0);
     105    T (d, "",    1);
     106    T (d, "",    2);
     107    T (d, "",    3);
     108    T (d, "123", 0);
     109    T (d, "123", 1);
     110    T (d, "123", 2);
     111    T (d, "123", 3);
     112    T (d, "123", 4);
     113    T (d, "123", 9);
     114  
     115    T (d, "123", sizeof "123");
     116    T (d, ar, sizeof ar);
     117  
     118    /* There is no overflow in the following calls but they are diagnosed
     119       by -Wstringop-truncation.  Verify that they aren'y also diagnosed
     120       by -Wstringop-overflow.  */
     121    T (d, s, strlen (s));
     122  
     123    {
     124      int n = strlen (s);
     125      T (d, s, n);
     126    }
     127  
     128    {
     129      unsigned n = strlen (s);
     130      T (d, s, n);
     131    }
     132  
     133    {
     134      size_t n;
     135      n = strlen (s);
     136      T (d, s, n);
     137    }
     138  
     139    {
     140      size_t n;
     141      n = strlen (s) - 1;
     142      T (d, s, n);
     143    }
     144  
     145    {
     146      /* This is diagnosed by -Wstringop-truncation.  Verify that it isn't
     147         also diagnosed by -Wstringop-overflow.  */
     148      size_t n = strlen (s) - strlen (s);
     149      T (d, s, n);
     150    }
     151  
     152    {
     153      /* This use of strncpy is certainly dubious and it could well be
     154         diagnosed by -Wstringop-truncation but it isn't.  */
     155      size_t n = i < strlen (s) ? i : strlen (s);   /* { dg-message "length computed here" "note" { xfail *-*-* } } */
     156      T (d, s, n);                  /* { dg-message ".strncpy\[^\n\r]* specified bound depends on the length of the source argument" "pr?????" { xfail *-*-* } } */
     157    }
     158  }