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