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
foo(const struct A * x,int y,const unsigned char * z)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 *
baz(const struct A * x,const unsigned char * z)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 "will always overflow" "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 }
138