(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
Wstringop-overflow-24.c
       1  /* PR middle-end/83859 - attribute to establish relation between parameters
       2     for buffer and its size
       3     Test to verify that -Wstringop-overflow warnings are issued even with
       4     no optimization for calls to user-defined functions with attribute
       5     access and with constant out-of-bounds arguments.
       6     { dg-do compile }
       7     { dg-options "-O0 -Wall" } */
       8  
       9  #define INT_MAX   __INT_MAX__
      10  #define INT_MIN   (-INT_MAX - 1)
      11  
      12  #define rdonly       __attribute__ ((access (read_only)))
      13  #define RDONLY(...)  __attribute__ ((access (read_only, __VA_ARGS__)))
      14  #define WRONLY(...)  __attribute__ ((access (write_only, __VA_ARGS__)))
      15  #define RDWR(...)    __attribute__ ((access (read_write, __VA_ARGS__)))
      16  
      17  typedef __INT32_TYPE__ int32_t;
      18  
      19  extern const char s1[1], s2[2], s3[3];
      20  extern char d1[1], d2[2], d3[3];
      21  
      22  /* Exercise that null pointers are allowed in functions declared with
      23     the attribute without a size operand.  */
      24  
      25  RDONLY (1) void
      26  rd1_int (const int32_t*);   // { dg-message "in a call to function 'rd1_int' declared with attribute 'access \\\(read_only, 1\\\)'" "note" }
      27  
      28  void test_rd1_int (void)
      29  {
      30    rd1_int (0);
      31  
      32    int32_t i = 0;
      33    rd1_int (&i);
      34  
      35    rd1_int ((int32_t*)s1);   // { dg-warning "reading 4 bytes from a region of size 1" }
      36  }
      37  
      38  /* Exercise null pointer detection in functions declared with
      39     the attribute and with non-zero size.  */
      40  
      41  RDONLY (2, 1) void
      42  rd2_1 (int, const void*);   // { dg-message "in a call to function 'rd2_1' declared with attribute 'access \\\(read_only, 2, 1\\\)" "note" }
      43  
      44  void test_rd2_1 (void)
      45  {
      46    rd2_1 (0, 0);
      47    rd2_1 (1, "");
      48    rd2_1 (1, 0);             // { dg-warning "argument 2 is null but the corresponding size argument 1 value is 1" }
      49  }
      50  
      51  WRONLY (3, 1) void
      52  wr3_1 (int, int, void*);    // { dg-message "in a call to function 'wr3_1' declared with attribute 'access \\\(write_only, 3, 1\\\)" "note" }
      53  
      54  void test_wr3_1 (void)
      55  {
      56    wr3_1 (0, 0, 0);
      57    wr3_1 (1, 0, d1);
      58    wr3_1 (2, 1, 0);          // { dg-warning "argument 3 is null but the corresponding size argument 1 value is 2" }
      59  }
      60  
      61  
      62  /* Exercise pointer to an incomplete type other than void.  */
      63  
      64  struct Incomplete;
      65  extern struct Incomplete inc;
      66  
      67  RDONLY (1) void
      68  rd_inc (const struct Incomplete*);
      69  
      70  void test_rd_inc (const struct Incomplete *pinc)
      71  {
      72    rd_inc (0);
      73  
      74    rd_inc (pinc);
      75    rd_inc ((const struct Incomplete*)s1);
      76  
      77    rd_inc ((const struct Incomplete*)&s1[1]);
      78    // { dg-warning "'rd_inc' reading 1 byte from a region of size 0" "past-the-end pointer" { target *-*-* } .-1 }
      79  }
      80  
      81  RDONLY (1, 2) void
      82  rd1_2_inc (const struct Incomplete*, unsigned);
      83  
      84  void test_rd1_2_inc (const struct Incomplete *pinc)
      85  {
      86    rd1_2_inc (0, 0);
      87    rd1_2_inc (0, 1);         // { dg-warning "argument 1 is null but the corresponding size argument 2 value is 1" }
      88  
      89    rd1_2_inc (pinc, 1);
      90    rd1_2_inc (&inc, 1);
      91  
      92    rd1_2_inc (pinc, 123);
      93    rd1_2_inc (&inc, 456);
      94  
      95    rd1_2_inc ((const struct Incomplete*)s3, 4);
      96    // { dg-warning "'rd1_2_inc' reading 4 bytes from a region of size 3" "small buffer cast to incomplete" { target *-*-* } .-1 }
      97  }
      98  
      99  
     100  /* Verify the handling of two attributes sharing the same size operand .  */
     101  
     102  RDONLY (1, 3) WRONLY (2, 3) void
     103  rd1_3_wr2_3 (const void*, void*, int);
     104  
     105  void test_rd1_3_wr2_3 (void)
     106  {
     107    rd1_3_wr2_3 (s1, d1, 0);
     108    rd1_3_wr2_3 (s1, d1, 1);
     109  
     110    rd1_3_wr2_3 (s1, d1, 2);
     111    // { dg-warning "'rd1_3_wr2_3' reading 2 bytes from a region of size 1" "read" { target *-*-* } .-1 }
     112    // { dg-warning "'rd1_3_wr2_3' writing 2 bytes into a region of size 1" "write" { target *-*-* } .-2 }
     113  
     114    rd1_3_wr2_3 (s1, d2, 2);
     115    // { dg-warning "'rd1_3_wr2_3' reading 2 bytes from a region of size 1" "read" { target *-*-* } .-1 }
     116  
     117    rd1_3_wr2_3 (s2, d1, 2);
     118    // { dg-warning "'rd1_3_wr2_3' writing 2 bytes into a region of size 1" "write" { target *-*-* } .-1 }
     119  }
     120  
     121  
     122  /* Verify the handling of multiple attributes of the same kind with
     123     out-of-order operands.  */
     124  
     125  RDONLY (1, 6) RDONLY (2, 5) RDONLY (3, 4) void
     126  rd1_6_2_5_3_4 (const void *s1, const void *s2, const void *s3,
     127  	       int         n3, int         n2, int         n1);
     128  
     129  void test_rd1_6_2_5_3_4 (void)
     130  {
     131    rd1_6_2_5_3_4 (s1, s2, s3, 4, 2, 1);   // { dg-warning "reading 4 bytes from a region of size 3" }
     132    rd1_6_2_5_3_4 (s1, s2, s3, 3, 5, 1);   // { dg-warning "reading 5 bytes from a region of size 2" }
     133    rd1_6_2_5_3_4 (s1, s2, s3, 3, 2, 6);   // { dg-warning "reading 6 bytes from a region of size 1" }
     134  }
     135  
     136  
     137  /* Verify the handling of multiple attributes of different kinds with
     138     out-of-order operands.  */
     139  
     140  RDONLY (1, 6) WRONLY (2, 5) RDONLY (3, 4) void
     141  rd1_6_wr2_5_rd3_4 (const void *s1, void *d2, const void *s3,
     142  		   int         n3, int   n2, int         n1);
     143  
     144  void test_rd1_6_wr2_5_rd3_4 (void)
     145  {
     146    rd1_6_wr2_5_rd3_4 (s1, d2, s3, 7, 2, 1);   // { dg-warning "reading 7 bytes from a region of size 3" }
     147    rd1_6_wr2_5_rd3_4 (s1, d2, s3, 3, 8, 1);   // { dg-warning "writing 8 bytes into a region of size 2" }
     148    rd1_6_wr2_5_rd3_4 (s1, d2, s3, 3, 2, 9);   // { dg-warning "reading 9 bytes from a region of size 1" }
     149  }
     150  
     151  
     152  RDONLY (6, 1) WRONLY (5, 2) RDWR (4, 3) void
     153  rd6_1_wr5_2_rd4_3 (int   n1, int   n2, int         n3,
     154  		   void *d3, void *d2, const void *s1);
     155  
     156  void test_rd6_1_wr5_2_rd4_3 (void)
     157  {
     158    rd6_1_wr5_2_rd4_3 (7, 2, 1, d1, d2, s3);   // { dg-warning "reading 7 bytes from a region of size 3" }
     159    rd6_1_wr5_2_rd4_3 (3, 8, 1, d1, d2, s3);   // { dg-warning "writing 8 bytes into a region of size 2" }
     160    rd6_1_wr5_2_rd4_3 (3, 2, 9, d1, d2, s3);   // { dg-warning "accessing 9 bytes in a region of size 1" }
     161  }
     162  
     163  
     164  RDONLY (1, 3) WRONLY (2, 4) void
     165  rd1_3_wr2_4 (const void*, void*, int, int);
     166  
     167  void test_rd1_3_wr2_4 (const void *s, void *d, int n1, int n2)
     168  {
     169    rd1_3_wr2_4 (s, d, 1, 2);
     170    rd1_3_wr2_4 (s, d, 123, 456);
     171    rd1_3_wr2_4 (s, d, INT_MAX, INT_MAX);
     172    rd1_3_wr2_4 (s, d, -1, 2);    // { dg-warning "argument 3 value -1 is negative" }
     173  
     174    const char s11[11] = "0123456789";
     175  
     176    rd1_3_wr2_4 (s11, d, 11, n2);
     177    rd1_3_wr2_4 (s11, d, 12, n2);   // { dg-warning "'rd1_3_wr2_4' reading 12 bytes from a region of size 11" }
     178  }
     179  
     180  
     181  /* Verify that function pointers are handled.  */
     182  
     183  RDONLY (1) void (*pfrd1)(const void*, const void*);
     184  
     185  void test_pfrd1 (void)
     186  {
     187    pfrd1 (0, 0);
     188    pfrd1 ("", "");
     189  
     190    pfrd1 ("", "" + 1);
     191    pfrd1 ("" + 1, "");   // { dg-warning "reading 1 byte from a region of size 0" }
     192  }
     193  
     194  
     195  WRONLY (4, 3) void (*pfwr4_3)(int, const char*, int, int32_t*);
     196  
     197  void test_pfwr4_3 (void)
     198  {
     199    pfwr4_3 (0, 0, 0, 0);
     200  
     201    int32_t i;
     202    pfwr4_3 (3, "", 0, &i + 1);
     203    pfwr4_3 (5, "", 1, &i + 1);   // { dg-warning "writing 4 bytes into a region of size 0" }
     204  }