(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
Wstringop-overflow-59.c
       1  /* PR middle-end/92936 - missing warning on a past-the-end store to a PHI
       2     Exercise warnings for writing into one of two or more allocated objects.
       3     { dg-do compile }
       4     { dg-options "-O2 -Wall -Wno-array-bounds -ftrack-macro-expansion=0" } */
       5  
       6  #include "range.h"
       7  
       8  #define INT_MAX __INT_MAX__
       9  
      10  extern void* malloc (size_t);
      11  extern void* memset (void*, int, size_t);
      12  #define memset(d, c, n) sink (memset (d, c, n))
      13  
      14  void sink (int, ...);
      15  #define sink(...) sink (0, __VA_ARGS__)
      16  
      17  volatile int cond1, cond2, x;
      18  
      19  #define CHOOSE_MALLOC_2(n1, n2)			\
      20    (cond1 ? malloc (n1) : malloc (n2))
      21  #define CHOOSE_MALLOC_3(n1, n2, n3)					\
      22    (cond1 < 0 ? malloc (n1) : 0 < cond1 ? malloc (n2) : malloc (n3))
      23  
      24  
      25  void memset_malloc_2 (void)
      26  {
      27    {
      28      char *p0_1 = CHOOSE_MALLOC_2 (0, 1);
      29  
      30      memset (p0_1, 0, 0);
      31      /* Writing more than the smallest destination should trigger a "may
      32         write" warning if the access is unconditionally reachable from
      33         the block where the pointer to either object is assigned.  */
      34      memset (p0_1, 0, 1);
      35      memset (p0_1, 0, 2);      // { dg-warning "memset' writing 2 bytes into a region of size 1 " }
      36      memset (p0_1, 0, 9);      // { dg-warning "memset' writing 9 bytes into a region of size 1 " }
      37    }
      38  
      39    {
      40      char *p0_x = CHOOSE_MALLOC_2 (0, x);
      41  
      42      memset (p0_x, 0, 0);
      43      memset (p0_x, 0, 1);
      44      memset (p0_x, 0, 2);
      45      memset (p0_x, 0, 12345);
      46    }
      47  
      48    {
      49      char *px_x = CHOOSE_MALLOC_2 (x, x);
      50  
      51      memset (px_x, 0, 0);
      52      memset (px_x, 0, 1);
      53      memset (px_x, 0, 2);
      54      memset (px_x, 0, 12345);
      55    }
      56  
      57    {
      58      char *p3_5 = CHOOSE_MALLOC_2 (3, 5);
      59  
      60      memset (p3_5, 0, 1);
      61      memset (p3_5, 0, 3);
      62      memset (p3_5, 0, 4);
      63      memset (p3_5, 0, 5);
      64      memset (p3_5, 0, 6);      // { dg-warning "memset' writing 6 bytes into a region of size 5 " }
      65    }
      66  
      67    {
      68      char *p5_3 = CHOOSE_MALLOC_2 (5, 3);
      69  
      70      memset (p5_3, 0, 3);
      71      memset (p5_3, 0, 4);
      72      memset (p5_3, 0, 5);
      73      memset (p5_3, 0, 6);      // { dg-warning "memset' writing 6 bytes into a region of size 5 " }
      74    }
      75  
      76    {
      77      char *px_3 = CHOOSE_MALLOC_2 (x, 3);
      78  
      79      memset (px_3, 0, 1);
      80      memset (px_3, 0, 3);
      81      memset (px_3, 0, 4);
      82      memset (px_3, 0, 1234);
      83    }
      84  
      85    {
      86      char *p5_x = CHOOSE_MALLOC_2 (5, x);
      87  
      88      memset (p5_x, 0, 1);
      89      memset (p5_x, 0, 5);
      90      memset (p5_x, 0, 6);
      91      memset (p5_x, 0, 1234);
      92    }
      93  
      94  }
      95  
      96  
      97  void memset_malloc_3 (void)
      98  {
      99    {
     100      char *p0_1_2 = CHOOSE_MALLOC_3 (0, 1, 2);
     101      memset (p0_1_2, 0, 0);
     102      memset (p0_1_2, 0, 1);
     103      memset (p0_1_2, 0, 2);
     104      memset (p0_1_2, 0, 3);    // { dg-warning "memset' writing 3 bytes into a region of size 2 " }
     105      memset (p0_1_2, 0, 9);    // { dg-warning "memset' writing 9 bytes into a region of size 2 " }
     106    }
     107  
     108    {
     109      char *p0_2_x = CHOOSE_MALLOC_3 (0, 2, x);
     110  
     111      memset (p0_2_x, 0, 0);
     112      memset (p0_2_x, 0, 1);
     113      memset (p0_2_x, 0, 3);
     114      memset (p0_2_x, 0, 9);
     115    }
     116  
     117    {
     118      char *p3_4_5 = CHOOSE_MALLOC_3 (3, 4, 5);
     119  
     120      memset (p3_4_5, 0, 3);
     121      memset (p3_4_5, 0, 4);
     122      memset (p3_4_5, 0, 5);
     123      memset (p3_4_5, 0, 6);    // { dg-warning "memset' writing 6 bytes into a region of size 5 " }
     124    }
     125  
     126    {
     127      char *p5_3_4 = CHOOSE_MALLOC_3 (5, 3, 4);
     128  
     129      memset (p5_3_4, 0, 3);
     130      memset (p5_3_4, 0, 4);
     131      memset (p5_3_4, 0, 5);
     132      memset (p5_3_4, 0, 6);    // { dg-warning "memset' writing 6 bytes into a region of size 5 " }
     133    }
     134  
     135    {
     136      char *p9_8_7 = CHOOSE_MALLOC_3 (9, 8, 7);
     137  
     138      memset (p9_8_7, 0, 7);
     139      memset (p9_8_7, 0, 8);
     140      memset (p9_8_7, 0, 9);
     141      memset (p9_8_7, 0, 10);   // { dg-warning "memset' writing 10 bytes into a region of size 9 " }
     142    }
     143  }
     144  
     145  
     146  /* Verify conditionally writing into one of two objects with the same
     147     size.  */
     148  
     149  void memset_malloc_2_same_size (int i)
     150  {
     151    {
     152      char a4_1[4], a4_2[4];
     153      char *p4 = cond1 ? a4_1 : a4_2;
     154  
     155      memset (p4, 0, 1);
     156      memset (p4, 0, 2);
     157      memset (p4, 0, 3);
     158      memset (p4, 0, 4);
     159      memset (p4, 0, 5);        // { dg-warning "memset' writing 5 bytes into a region of size 4" }
     160    }
     161  
     162    {
     163      char a4_1[4];             // { dg-message "destination object 'a4_1" "note" }
     164      char a4_2[4];             // { dg-message "destination object 'a4_2" "note" }
     165      char *p4 = cond1 ? a4_1 : a4_2;
     166      char *p4_i = p4 + i;
     167  
     168      memset (p4_i, 0, 5);      // { dg-warning "memset' writing 5 bytes into a region of size 4" }
     169    }
     170  
     171    {
     172      if (i < 1)
     173        i = 1;
     174  
     175      char a4_1[4];             // { dg-message "at offset \\\[1, 4] into destination object 'a4_1" "note" }
     176      char a4_2[4];             // { dg-message "at offset \\\[1, 4] into destination object 'a4_2" "note" }
     177      char *p4 = cond1 ? a4_1 : a4_2;
     178      char *p4_i = p4 + i;
     179  
     180      memset (p4_i, 0, 3);
     181      memset (p4_i, 0, 4);      // { dg-warning "memset' writing 4 bytes into a region of size 3 " }
     182    }
     183  }
     184  
     185  
     186  void memset_malloc_2_off (void)
     187  {
     188    int i1 = SR (1, INT_MAX);
     189    int i2 = SR (2, INT_MAX);
     190  
     191    {
     192      char a5[5];               // { dg-warning "at offset [1, 5] into destination object 'a5'
     193      char a7[7];               // { dg-warning "at offset [2, 7] into destination object 'a7'
     194      char *p5_p1 = a5 + i1;
     195      char *p7_p2 = a7 + i2;
     196      char *p5_7 = cond1 ? p5_p1 : p7_p2;
     197  
     198      memset (p5_7, 0, 1);
     199      memset (p5_7, 0, 2);
     200      memset (p5_7, 0, 3);
     201      memset (p5_7, 0, 4);
     202      memset (p5_7, 0, 5);
     203      /* The warning code conservatively "merges" both the sizes and the offsets
     204         into A5 and A7 and so only the second store below is diagnosed but not
     205         the first.  See PR 103215.  The logic needs to be tightened up.  */
     206      memset (p5_7, 0, 6);      // { dg-warning "memset' writing 6 bytes into a region of size 5 " "pr??????" { xfail *-*-* } }
     207      memset (p5_7, 0, 7);      // { dg-warning "memset' writing 7 bytes into a region of size 6 " }
     208    }
     209  
     210    int i3 = SR (3, INT_MAX);
     211  
     212    {
     213      char a5[5];
     214      // { dg-message "at offset \\\[3, 5] into destination object 'a5'" "note" { target *-*-* } .-1 }
     215      // { dg-message "at offset \\\[2, 5] into destination object 'a5'" "note" { target *-*-* } .-2 }
     216      // { dg-message "at offset \\\[1, 5] into destination object 'a5'" "note" { target *-*-* } .-3 }
     217      // { dg-message ": destination object 'a5'" "note" { target *-*-* } .-4 }
     218      char a9[9];
     219      // { dg-message "at offset \\\[4, 9] into destination object 'a9'" "note" { target *-*-* } .-1 }
     220      // { dg-message "at offset \\\[3, 9] into destination object 'a9'" "note" { target *-*-* } .-2 }
     221      // { dg-message "at offset \\\[2, 9] into destination object 'a9'" "note" { target *-*-* } .-3 }
     222      // { dg-message "at offset \\\[1, 9] into destination object 'a9'" "note" { target *-*-* } .-4 }
     223      // { dg-message ": destination object 'a9'" "pr??????" { xfail *-*-* } .-5 }
     224      char *p5_p2 = a5 + i2;    // 3 bytes left
     225      char *p9_p3 = a9 + i3;    // 6 bytes left
     226      char *p =
     227        cond1 ? p5_p2 : p9_p3;  // [3 - 6] bytes left
     228      char *q = p + i1;         // [2 - 5] bytes left
     229  
     230      memset (q, 0, 1);
     231      memset (q, 0, 2);
     232      memset (q, 0, 3);
     233      memset (q, 0, 4);
     234      memset (q, 0, 5);
     235      memset (q, 0, 6);         // { dg-warning "memset' writing 6 bytes into a region of size 5" "pr??????" { xfail *-*-* } }
     236      memset (q, 0, 7);         // { dg-warning "memset' writing 7 bytes into a region of size 6" }
     237  
     238      --q;                      // [3 - 6] bytes left
     239      memset (q, 0, 1);
     240      memset (q, 0, 2);
     241      memset (q, 0, 3);
     242      memset (q, 0, 4);
     243      memset (q, 0, 5);
     244      memset (q, 0, 6);
     245      memset (q, 0, 7);         // { dg-warning "memset' writing 7 bytes into a region of size 6" "pr??????" { xfail *-*-* } }
     246      memset (q, 0, 8);         // { dg-warning "memset' writing 8 bytes into a region of size 7" }
     247  
     248      --q;                      // [4 - 7] bytes left
     249      memset (q, 0, 1);
     250      memset (q, 0, 2);
     251      memset (q, 0, 3);
     252      memset (q, 0, 4);
     253      memset (q, 0, 5);
     254      memset (q, 0, 6);
     255      memset (q, 0, 7);
     256      memset (q, 0, 8);         // { dg-warning "memset' writing 8 bytes into a region of size 7" "pr??????" { xfail *-*-* } }
     257      memset (q, 0, 9);         // { dg-warning "memset' writing 9 bytes into a region of size 8" }
     258  
     259      int m1_x = SR (-1, INT_MAX);
     260      int m2_x = SR (-2, INT_MAX);
     261  
     262      q += cond2 ? m1_x : m2_x;   // [5 - 9] bytes left
     263  
     264      memset (q, 0, 1);
     265      memset (q, 0, 2);
     266      memset (q, 0, 3);
     267      memset (q, 0, 4);
     268      memset (q, 0, 5);
     269      memset (q, 0, 6);
     270      memset (q, 0, 7);
     271      memset (q, 0, 8);
     272      memset (q, 0, 9);
     273      memset (q, 0, 10);        // { dg-warning "memset' writing 10 bytes into a region of size 9" }
     274    }
     275  }