(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
Wstringop-overflow-62.c
       1  /* Test for MIN and MAX expressions involving pointers.
       2    { dg-do compile }
       3    { dg-options "-O2 -Wall -Wno-array-bounds -ftrack-macro-expansion=0" } */
       4  
       5  #include "range.h"
       6  
       7  #define INT_MAX __INT_MAX__
       8  
       9  #define MIN(x, y) ((x) < (y) ? (x) :  (y))
      10  #define MAX(x, y) ((x) < (y) ? (y) :  (x))
      11  
      12  typedef __SIZE_TYPE__ size_t;
      13  
      14  void* memset (void*, int, size_t);
      15  #define memset(...) sink (memset (__VA_ARGS__))
      16  
      17  void sink (void*, ...);
      18  
      19  volatile int cond, vi;
      20  char* volatile ptr;
      21  
      22  void test_min (void)
      23  {
      24    const int i1 = SR (1, INT_MAX);
      25    const int i2 = SR (2, INT_MAX);
      26  
      27    {
      28      /* Exercise both pointers pointing to a different unknown object plus
      29         positive constant offset.  Since PTR is volatile P1 and P2 cannot
      30         normally be considered to point to the same object.  It can only
      31         be inferred from the MIN expression.  */
      32      char *p1 = ptr + 1;
      33      char *p2 = ptr + 2;
      34  
      35      char *q = MIN (p1, p2);
      36  
      37      memset (q, 0, 1);
      38      memset (q, 0, 2);
      39      memset (q, 0, INT_MAX);
      40      // { dg-warning "writing 2147483647 bytes into a region of size 2147483646" "ilp32" { target ilp32 } .-1 }
      41      memset (q, 0, DIFF_MAX - 2);
      42      memset (q, 0, DIFF_MAX);
      43      // { dg-warning "writing 2147483647 bytes into a region of size 2147483646" "ilp32" { target ilp32 } .-1 }
      44      // { dg-warning "writing 9223372036854775807 bytes into a region of size 9223372036854775806" "not-ilp32" { target { ! ilp32 } } .-2 }
      45    }
      46  
      47    {
      48      /* Exercise both pointers pointing to a different unknown object plus
      49         variable offset.  */
      50      char *p1 = ptr + vi;
      51      char *p2 = ptr + vi;
      52  
      53      char *q = MIN (p1, p2);
      54  
      55      memset (q, 0, 1);
      56      memset (q, 0, 2);
      57      memset (q, 0, INT_MAX);
      58    }
      59  
      60    {
      61      /* Exercise both pointers pointing to the same object plus constant
      62         offset.  */
      63      char a2[2];               // { dg-message "at offset 1 into destination object 'a2' of size 2" "note" }
      64      char *p1 = a2 + 1;
      65      char *p2 = a2 + 2;
      66  
      67      char *q = MIN (p1, p2);
      68  
      69      memset (q, 0, 1);
      70      memset (q, 0, 2);         // { dg-warning "writing 2 bytes into a region of size 1 " }
      71    }
      72  
      73    {
      74      /* Exercise both pointers pointing to the same object plus offset
      75         in a known range.  */
      76      char a3[3];               // { dg-message "at offset \\\[1, 3] into destination object 'a3'" "note" }
      77      char *pi = a3 + i1;
      78      char *pj = a3 + i2;
      79  
      80      char *q = MIN (pi, pj);
      81  
      82      memset (q, 0, 1);
      83      memset (q, 0, 2);
      84      memset (q, 0, 3);         // { dg-warning "writing 3 bytes into a region of size 2 " }
      85    }
      86  
      87    {
      88      /* Exercise both pointers pointing to the same object plus variable
      89         offset.  Verify that no offset is mentioned in the note (since
      90         its unknown, printing its full range is unnecessary).  */
      91      char a4[4];               // { dg-message ": destination object 'a4'" "note" }
      92      char *pi = a4 + vi;
      93      char *pj = a4 + vi;
      94  
      95      char *q = MIN (pi, pj);
      96  
      97      memset (q, 0, 1);
      98      memset (q, 0, 2);
      99      memset (q, 0, 3);
     100      memset (q, 0, 4);
     101      memset (q, 0, 5);         // { dg-warning "writing 5 bytes into a region of size 4 " }
     102    }
     103  
     104    {
     105      /* Exercise a pointer pointing to a known object with one pointing
     106         to an unknown object.  */
     107      char a5[5];               // { dg-message ": destination object 'a5'" "note" }
     108      char *p = ptr;
     109      char *q = MIN (p, a5);
     110  
     111      memset (q, 0, 1);
     112      memset (q, 0, 2);
     113      memset (q, 0, 5);
     114      memset (q, 0, 6);         // { dg-warning "writing 6 bytes into a region of size 5 " }
     115    }
     116  
     117    {
     118      /* Exercise a pointer pointing to a known object plus constant offset
     119         with one pointing to an unknown object.  */
     120      char a6[6];               // { dg-message "(at offset 1 into )?destination object 'a6'" "note" }
     121      char *p1 = ptr;
     122      char *p2 = a6 + 1;
     123      char *q = MIN (p1, p2);
     124  
     125      memset (q, 0, 1);
     126      memset (q, 0, 2);
     127      memset (q, 0, 6);
     128      memset (q, 0, 7);         // { dg-warning "writing 7 bytes into a region of size 6 " }
     129    }
     130  
     131    {
     132      /* Exercise a pointer pointing to a known object with one pointing
     133         to an unknown object plus constant offset.  */
     134      char a7[7];               // { dg-message ": destination object 'a7'" "note" }
     135      char *p1 = a7;
     136      char *p2 = ptr + 1;
     137      /* Since p1 points to a7[0] it must be less than any pointer to a7
     138         plus positive offset, and so Q == P1.  */
     139      char *q = MIN (p1, p2);
     140  
     141      memset (q, 0, 1);
     142      memset (q, 0, 2);
     143      memset (q, 0, 3);
     144      memset (q, 0, 7);
     145      memset (q, 0, 8);         // { dg-warning "writing 8 bytes into a region of size 7 " }
     146    }
     147  
     148    {
     149      /* Exercise a pointer pointing to a known object plus constant offset
     150         with one pointing to an unknown object plus a different constant
     151         offset.  */
     152      char a8[8];               // { dg-message "at offset 1 into destination object 'a8'" "note" }
     153      char *p1 = a8 + 1;
     154      char *p2 = ptr + 2;
     155      /* Since P1 points to A8[1] it must be less than or equal to any
     156         pointer to A8 plus positive offset.  Either way, Q must point
     157         to A8[1].  */
     158      char *q = MIN (p1, p2);
     159  
     160      memset (q, 0, 1);
     161      memset (q, 0, 2);
     162      memset (q, 0, 7);
     163      memset (q, 0, 8);         // { dg-warning "writing 8 bytes into a region of size 7 " }
     164    }
     165  
     166    {
     167      /* Same as above but with larger offsets.  */
     168      char a9[9];               // { dg-message "at offset 3 into destination object 'a9'" "note" }
     169      char *p1 = a9 + 3;
     170      char *p2 = ptr + 4;
     171      /* Since P1 points to A9[3] it must be less than or equal to any
     172         pointer anywhere into A9 plus 4, so Q must point to A9[3].  */
     173      char *q = MIN (p1, p2);
     174  
     175      memset (q, 0, 1);
     176      memset (q, 0, 2);
     177      memset (q, 0, 6);
     178      memset (q, 0, 7);         // { dg-warning "writing 7 bytes into a region of size 6 " }
     179    }
     180  
     181    {
     182      /* Same as above but with the offsets reversed.  */
     183      char a10[10];              // { dg-message "at offset 5 into destination object 'a10'" "note" }
     184      char *p1 = a10 + 10;
     185      char *p2 = ptr + 5;
     186      /* Since P1 points just past the end of A10 it could be either less
     187         or equal to another pointer anywhere into A10 plus 3 because
     188         the other pointer itself could start at a non-zero offset that's
     189         not reflected in the determined offset).  */
     190      char *q = MIN (p1, p2);
     191  
     192      memset (q, 0, 1);
     193      memset (q, 0, 2);
     194      memset (q, 0, 5);
     195      memset (q, 0, 6);         // { dg-warning "writing 6 bytes into a region of size 5 " }
     196    }
     197  
     198    {
     199      char a3[3];               // { dg-message ": destination object 'a3'" "note" }
     200      char *p1 = ptr;
     201      char *p2 = a3 + i1;
     202      char *q = MIN (p1, p2);
     203  
     204      memset (q, 0, 1);
     205      memset (q, 0, 2);
     206      memset (q, 0, 3);
     207      memset (q, 0, 4);         // { dg-warning "writing 4 bytes into a region of size 3 " }
     208    }
     209  }
     210  
     211  
     212  void test_max (void)
     213  {
     214    const int i1 = SR (1, INT_MAX);
     215    const int i2 = SR (2, INT_MAX);
     216  
     217    {
     218      /* Exercise both pointers pointing to the same object plus constant
     219         offset.  */
     220      char a2[2];
     221      char *pi = a2 + 1;
     222      char *pj = a2 + 2;
     223  
     224      char *q = MAX (pi, pj);
     225  
     226      memset (q, 0, 1);         // { dg-warning "writing 1 byte into a region of size 0 " }
     227      memset (q, 0, 2);         // { dg-warning "writing 2 bytes into a region of size 0 " }
     228    }
     229  
     230    {
     231      /* Exercise both pointers pointing to the same object plus offset
     232         in a known range.  */
     233      char a3[3];               // { dg-message "at offset \\\[1, 3] into destination object 'a3'" "note" }
     234      char *pi = a3 + i1;
     235      char *pj = a3 + i2;
     236  
     237      char *q = MAX (pi, pj);
     238  
     239      memset (q, 0, 1);
     240      memset (q, 0, 2);
     241      memset (q, 0, 3);         // { dg-warning "writing 3 bytes into a region of size 2 " }
     242    }
     243  
     244    {
     245      /* Exercise both pointers pointing to the same object plus variable
     246         offset.  Verify that no offset is mentioned in the note (since
     247         its unknown, printing its full range is unnecessary).  */
     248      char a4[4];               // { dg-message ": destination object 'a4'" "note" }
     249      char *pi = a4 + vi;
     250      char *pj = a4 + vi;
     251  
     252      char *q = MAX (pi, pj);
     253  
     254      memset (q, 0, 1);
     255      memset (q, 0, 2);
     256      memset (q, 0, 3);
     257      memset (q, 0, 4);
     258      memset (q, 0, 5);         // { dg-warning "writing 5 bytes into a region of size 4 " }
     259    }
     260  
     261    {
     262      /* Exercise a pointer pointing to a known object with one pointing
     263         to an unknown object.  */
     264      char a5[5];               // { dg-message ": destination object 'a5'" "note" }
     265      char *p = ptr;
     266      char *q = MAX (p, a5);
     267  
     268      memset (q, 0, 1);
     269      memset (q, 0, 2);
     270      memset (q, 0, 5);
     271      memset (q, 0, 6);         // { dg-warning "writing 6 bytes into a region of size 5 " }
     272    }
     273  
     274    {
     275      /* Exercise a pointer pointing to a known object plus constant offset
     276         with one pointing to an unknown object.  */
     277      char a6[6];               // { dg-message "at offset 1 into destination object 'a6'" "note" }
     278      char *p1 = ptr;
     279      char *p2 = a6 + 1;
     280      char *q = MAX (p1, p2);
     281  
     282      memset (q, 0, 1);
     283      memset (q, 0, 5);
     284      memset (q, 0, 6);         // { dg-warning "writing 6 bytes into a region of size 5 " }
     285      memset (q, 0, 7);         // { dg-warning "writing 7 bytes into a region of size 5 " }
     286    }
     287  
     288    {
     289      /* Exercise a pointer pointing to a known object with one pointing
     290         to an unknown object plus constant offset.  */
     291      char a7[7];               // { dg-message "at offset 1 into destination object 'a7'" "note" }
     292      char *p1 = a7;
     293      char *p2 = ptr + 1;
     294      /* Since p1 points to a7[0] it must be less than any pointer to a7
     295         plus positive offset, and so Q == P2.  */
     296      char *q = MAX (p1, p2);
     297  
     298      memset (q, 0, 1);
     299      memset (q, 0, 6);
     300      memset (q, 0, 7);         // { dg-warning "writing 7 bytes into a region of size 6 " }
     301      memset (q, 0, 8);         // { dg-warning "writing 8 bytes into a region of size 6 " }
     302    }
     303  
     304    {
     305      /* Exercise a pointer pointing to a known object plus constant offset
     306         with one pointing to an unknown object plus a different constant
     307         offset.  */
     308      char a8[8];               // { dg-message "at offset 2 into destination object 'a8'" "note" }
     309      char *p1 = a8 + 1;
     310      char *p2 = ptr + 2;
     311      /* Since P1 points to A8[1] it must be less than or equal to any
     312         pointer to A8 plus positive offset.  Either way, Q must point
     313         to A8[2].  */
     314      char *q = MAX (p1, p2);
     315  
     316      memset (q, 0, 1);
     317      memset (q, 0, 6);
     318      memset (q, 0, 7);         // { dg-warning "writing 7 bytes into a region of size 6 " }
     319      memset (q, 0, 8);         // { dg-warning "writing 8 bytes into a region of size 6 " }
     320    }
     321  
     322    {
     323      /* Same as above but with larger offsets.  */
     324      char a9[9];               // { dg-message "at offset 4 into destination object 'a9'" "note" }
     325      char *p1 = a9 + 3;
     326      char *p2 = ptr + 4;
     327      /* Since P1 points to A9[3] it must be less than or equal to any
     328         pointer anywhere into A9 plus 4, so Q must point to A9[4].  */
     329      char *q = MAX (p1, p2);
     330  
     331      memset (q, 0, 1);
     332      memset (q, 0, 2);
     333      memset (q, 0, 5);
     334      memset (q, 0, 6);         // { dg-warning "writing 6 bytes into a region of size 5 " }
     335    }
     336  
     337    {
     338      /* Same as above but with the offsets reversed.  */
     339      char a10[10];              // { dg-message "at offset 10 into destination object 'a10'" "note" }
     340      char *p1 = a10 + 10;
     341      char *p2 = ptr + 5;
     342      /* Since P1 points just past the end of A10 it could be either less
     343         or equal to another pointer anywhere into A10 plus 3 because
     344         the other pointer itself could start at a non-zero offset that's
     345         not reflected in the determaxed offset).  */
     346      char *q = MAX (p1, p2);
     347  
     348      memset (q, 0, 1);         // { dg-warning "writing 1 byte into a region of size 0 " }
     349    }
     350  
     351    {
     352      char a11[11];             // { dg-message "at offset \\\[1, 11] into destination object 'a11'" "note" }
     353      char *p1 = ptr;
     354      char *p2 = a11 + i1;
     355      char *q = MAX (p1, p2);
     356  
     357      memset (q, 0, 1);
     358      memset (q, 0, 2);
     359      memset (q, 0, 10);
     360      memset (q, 0, 11);        // { dg-warning "writing 11 bytes into a region of size 10 " }
     361    }
     362  }
     363