(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
builtin-stringop-chk-2.c
       1  /* This file was miscompiled by an earlier version of the object size
       2     checking patch.  Object size in one of the memcpy calls was
       3     incorrectly determined to be 0 while it should be (size_t) -1
       4     (== unknown).  */
       5  /* { dg-do compile } */
       6  /* { dg-options "-O2 -ftrack-macro-expansion=0" } */
       7  
       8  #include "../gcc.c-torture/execute/builtins/chk.h"
       9  
      10  void *bar (int);
      11  extern void *malloc (__SIZE_TYPE__);
      12  
      13  struct A
      14  {
      15    int i, j, k;
      16  };
      17  
      18  /* Here all object sizes are not known at compile time.  There
      19     should be no warning, nor any checker functions called.  */
      20  
      21  void
      22  foo (const struct A *x, int y, const unsigned char *z)
      23  {
      24    unsigned int b;
      25    unsigned char *c = 0;
      26  
      27    b = (x->i & 0xff) == 1 ? 3 : 4;
      28    if (y)
      29      c = bar (x->j * x->k);
      30  
      31    const unsigned char *d = z;
      32    unsigned char *e = c;
      33    unsigned char *f = c + x->j * x->k;
      34    int g = 0;
      35  
      36    while (e < f)
      37      {
      38        unsigned int h = *d++;
      39  
      40        if (h & 128)
      41  	{
      42  	  h = h - 128;
      43  	  g = e + h * b > f;
      44  	  if (g)
      45  	    h = (f - e) / b;
      46  	  if (b < 4)
      47  	    do
      48  	      {
      49  		memcpy (e, d, 3);
      50  		e += 3;
      51  	      }
      52  	    while (--h);
      53  	  else
      54  	    do
      55  	      {
      56  		memcpy (e, d, 4);
      57  		e += 4;
      58  	      }
      59  	    while (--h);
      60  	  d += b;
      61  	}
      62        else
      63  	{
      64  	  h *= b;
      65  	  g = e + h > f;
      66  	  if (g)
      67  	    h = f - e;
      68  	  memcpy (e, d, h);
      69  	  e += h;
      70  	  d += h;
      71  	}
      72      }
      73  }
      74  
      75  /* The same routine, slightly modified:
      76     1) c has known size at compile time
      77     2) e += h was changed into e += 16.
      78        GCC could actually through VRP determine that
      79        in e += h is (h >= 0 && h <= 127), thus know
      80        it is pointer addition and not subtraction and
      81        know e's __builtin_object_size (e, 0) is at 512,
      82        but we are not there yet.  */
      83  
      84  unsigned char *
      85  baz (const struct A *x, const unsigned char *z)
      86  {
      87    unsigned int b;
      88    unsigned char *c = 0;
      89  
      90    b = (x->i & 0xff) == 1 ? 3 : 4;
      91    c = malloc (512);
      92  
      93    const unsigned char *d = z;
      94    unsigned char *e = c;
      95    unsigned char *f = c + x->j * x->k;
      96    int g = 0;
      97  
      98    while (e < f)
      99      {
     100        unsigned int h = *d++;
     101  
     102        if (h & 128)
     103  	{
     104  	  h = h - 128;
     105  	  g = e + h * b > f;
     106  	  if (g)
     107  	    h = (f - e) / b;
     108  	  if (b < 4)
     109  	    do
     110  	      {
     111  		memcpy (e, d, 3);
     112  		e += 3;
     113  	      }
     114  	    while (--h);
     115  	  else
     116  	    do
     117  	      {
     118  		memcpy (e, d, 513); /* { dg-warning "writing" "memcpy" } */
     119  		e += 4;
     120  	      }
     121  	    while (--h);
     122  	  d += b;
     123  	}
     124        else
     125  	{
     126  	  h *= b;
     127  	  g = e + h > f;
     128  	  if (g)
     129  	    h = f - e;
     130  	  memcpy (e, d, h);
     131  	  /* e += h; */
     132  	  e += 16;
     133  	  d += h;
     134  	}
     135      }
     136    return c;
     137  }