1 /* PR middle-end/91631 - buffer overflow into an array member of a declared
2 object not detected
3 Test to verify that past-the-end accesses by string functions to member
4 arrays by-reference objects are diagnosed.
5 { dg-do compile }
6 { dg-options "-O2 -Wall -Wno-unused-local-typedefs -ftrack-macro-expansion=0" } */
7
8 extern char* strcpy (char*, const char*);
9 extern char* strcat (char*, const char*);
10
11 void sink (void*, ...);
12
13 #define S36 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
14
15 #define S(N) (S36 + sizeof (S36) - N - 1)
16
17 /* In the test macro, prevent the strcpy to memcpy transformation
18 by using a local array initialized with the string literal. Without
19 it, GCC transforms the strcpy call with memcpy which (unfortunately)
20 permits accesses that cross subobject boundaries. */
21 #define T(dst, ncpy, ncat) \
22 do { \
23 const char a[] = S36; \
24 strcpy (dst, a + sizeof a - ncpy - 1); \
25 const char b[] = S36; \
26 strcat (dst, b + sizeof b - ncat - 1); \
27 sink (dst); \
28 } while (0)
29
30
31 struct MemArrays
32 {
33 char a7[7]; // { dg-message "'a7' declared here" }
34 char a4[4]; // { dg-message "'a4' declared here" }
35 char a3[3]; // { dg-message "'a3' declared here" }
36 };
37
38 struct MemArrays gma;
39
strcat_value(void)40 void strcat_value (void)
41 {
42 T (gma.a7, 1, 1);
43 T (gma.a7, 1, 5);
44 T (gma.a7, 1, 6); // { dg-warning "'strcat' offset 7 from the object at 'gma' is out of the bounds of referenced subobject 'a7' with type 'char\\\[7]' at offset 0" }
45 T (gma.a7, 1, 7); // { dg-warning "'strcat' offset \\\[7, 8] from the object at 'gma' is out of the bounds of referenced subobject 'a7' with type 'char\\\[7]' at offset 0" }
46
47 T (gma.a7, 2, 1);
48 T (gma.a7, 2, 4);
49 T (gma.a7, 2, 5); // { dg-warning "'strcat' offset 7 from the object at 'gma' is out of the bounds of referenced subobject 'a7' with type 'char\\\[7]' at offset 0" }
50 T (gma.a7, 2, 6); // { dg-warning "'strcat' offset \\\[7, 8] from the object at 'gma' is out of the bounds of referenced subobject 'a7' with type 'char\\\[7]' at offset 0" }
51
52 T (gma.a7, 5, 1);
53 T (gma.a7, 5, 2); // { dg-warning "'strcat' offset 7 from the object at 'gma' is out of the bounds of referenced subobject 'a7' with type 'char\\\[7]' at offset 0" }
54
55 T (gma.a4, 1, 1);
56 T (gma.a4, 1, 2);
57 T (gma.a4, 1, 3); // { dg-warning "'strcat' offset 11 from the object at 'gma' is out of the bounds of referenced subobject 'a4' with type 'char\\\[4]' at offset 7" }
58 T (gma.a4, 1, 4); // { dg-warning "'strcat' offset \\\[11, 12] from the object at 'gma' is out of the bounds of referenced subobject 'a4' with type 'char\\\[4]' at offset 7" }
59
60 T (gma.a4, 2, 3); // { dg-warning "'strcat' offset \\\[11, 12] from the object at 'gma' is out of the bounds of referenced subobject 'a4' with type 'char\\\[4]' at offset 7" }
61
62 T (gma.a3, 1, 1);
63 T (gma.a3, 1, 2); // { dg-warning "'strcat' offset 14 from the object at 'gma' is out of the bounds of referenced subobject 'a3' with type 'char\\\[3]' at offset 11" }
64 }
65
66
strcat_ref(struct MemArrays * pma)67 void strcat_ref (struct MemArrays *pma)
68 {
69 T (pma->a7, 1, 1);
70 T (pma->a7, 1, 5);
71 T (pma->a7, 1, 6); // { dg-warning "'strcat' offset 7 from the object at 'pma' is out of the bounds of referenced subobject 'a7' with type 'char\\\[7]' at offset 0" }
72 T (pma->a7, 1, 7); // { dg-warning "'strcat' offset \\\[7, 8] from the object at 'pma' is out of the bounds of referenced subobject 'a7' with type 'char\\\[7]' at offset 0" }
73
74 T (pma->a7, 2, 1);
75 T (pma->a7, 2, 4);
76 T (pma->a7, 2, 5); // { dg-warning "'strcat' offset 7 from the object at 'pma' is out of the bounds of referenced subobject 'a7' with type 'char\\\[7]' at offset 0" }
77 T (pma->a7, 2, 6); // { dg-warning "'strcat' offset \\\[7, 8] from the object at 'pma' is out of the bounds of referenced subobject 'a7' with type 'char\\\[7]' at offset 0" }
78
79 T (pma->a4, 1, 1);
80 T (pma->a4, 1, 2);
81 T (pma->a4, 1, 3); // { dg-warning "'strcat' offset 11 from the object at 'pma' is out of the bounds of referenced subobject 'a4' with type 'char\\\[4]' at offset 7" }
82 T (pma->a4, 1, 4); // { dg-warning "'strcat' offset \\\[11, 12] from the object at 'pma' is out of the bounds of referenced subobject 'a4' with type 'char\\\[4]' at offset 7" }
83
84 T (pma->a4, 2, 3); // { dg-warning "'strcat' offset \\\[11, 12] from the object at 'pma' is out of the bounds of referenced subobject 'a4' with type 'char\\\[4]' at offset 7" }
85
86 T (pma->a3, 1, 1);
87 T (pma->a3, 1, 2); // { dg-warning "'strcat' offset 14 from the object at 'pma' is out of the bounds of referenced subobject 'a3' with type 'char\\\[3]' at offset 11" }
88 }
89
90
91 #define T2(dst1, dst2, ncpy, ncat) \
92 do { \
93 const char a[] = S36; \
94 strcpy (dst1, a + sizeof a - ncpy - 1); \
95 const char b[] = S36; \
96 strcat (dst2, b + sizeof b - ncat - 1); \
97 sink (dst1, dst2); \
98 } while (0)
99
100 struct ArraysOfMemArrays
101 {
102 struct MemArrays ma3[3];
103 } a3[3];
104
strcat_arrays_of_arrays_value(void)105 void strcat_arrays_of_arrays_value (void)
106 {
107 T2 (a3[0].ma3[0].a7, a3[0].ma3[0].a7, 6, 6); // { dg-warning "\\\[-Warray-bounds" }
108 T2 (a3[0].ma3[0].a7, a3[0].ma3[1].a7, 6, 6);
109 T2 (a3[0].ma3[0].a7, a3[0].ma3[2].a7, 6, 6);
110
111 T2 (a3[0].ma3[1].a7, a3[0].ma3[0].a7, 6, 6);
112 T2 (a3[0].ma3[1].a7, a3[0].ma3[1].a7, 6, 6); // { dg-warning "\\\[-Warray-bounds" }
113 T2 (a3[0].ma3[1].a7, a3[0].ma3[2].a7, 6, 6);
114
115 T2 (a3[0].ma3[2].a7, a3[0].ma3[0].a7, 6, 6);
116 T2 (a3[0].ma3[2].a7, a3[0].ma3[1].a7, 6, 6);
117 T2 (a3[0].ma3[2].a7, a3[0].ma3[2].a7, 6, 6); // { dg-warning "\\\[-Warray-bounds" }
118
119 T2 (a3[0].ma3[0].a7, a3[1].ma3[0].a7, 6, 6);
120 T2 (a3[0].ma3[0].a7, a3[1].ma3[1].a7, 6, 6);
121 T2 (a3[0].ma3[0].a7, a3[1].ma3[2].a7, 6, 6);
122
123 T2 (a3[0].ma3[1].a7, a3[1].ma3[0].a7, 6, 6);
124 T2 (a3[0].ma3[1].a7, a3[1].ma3[1].a7, 6, 6);
125 T2 (a3[0].ma3[1].a7, a3[1].ma3[2].a7, 6, 6);
126
127 T2 (a3[0].ma3[2].a7, a3[1].ma3[0].a7, 6, 6);
128 T2 (a3[0].ma3[2].a7, a3[1].ma3[1].a7, 6, 6);
129 T2 (a3[0].ma3[2].a7, a3[1].ma3[2].a7, 6, 6);
130
131 T2 (a3[0].ma3[0].a7, a3[2].ma3[0].a7, 6, 6);
132 T2 (a3[0].ma3[0].a7, a3[2].ma3[1].a7, 6, 6);
133 T2 (a3[0].ma3[0].a7, a3[2].ma3[2].a7, 6, 6);
134
135 T2 (a3[0].ma3[1].a7, a3[2].ma3[0].a7, 6, 6);
136 T2 (a3[0].ma3[1].a7, a3[2].ma3[1].a7, 6, 6);
137 T2 (a3[0].ma3[1].a7, a3[2].ma3[2].a7, 6, 6);
138
139 T2 (a3[0].ma3[2].a7, a3[2].ma3[0].a7, 6, 6);
140 T2 (a3[0].ma3[2].a7, a3[2].ma3[1].a7, 6, 6);
141 T2 (a3[0].ma3[2].a7, a3[2].ma3[2].a7, 6, 6);
142
143
144 T2 (a3[1].ma3[0].a7, a3[0].ma3[0].a7, 6, 6);
145 T2 (a3[1].ma3[0].a7, a3[0].ma3[1].a7, 6, 6);
146 T2 (a3[1].ma3[0].a7, a3[0].ma3[2].a7, 6, 6);
147
148 T2 (a3[1].ma3[1].a7, a3[0].ma3[0].a7, 6, 6);
149 T2 (a3[1].ma3[1].a7, a3[0].ma3[1].a7, 6, 6);
150 T2 (a3[1].ma3[1].a7, a3[0].ma3[2].a7, 6, 6);
151
152 T2 (a3[1].ma3[2].a7, a3[0].ma3[0].a7, 6, 6);
153 T2 (a3[1].ma3[2].a7, a3[0].ma3[1].a7, 6, 6);
154 T2 (a3[1].ma3[2].a7, a3[0].ma3[2].a7, 6, 6);
155
156 T2 (a3[1].ma3[0].a7, a3[1].ma3[0].a7, 6, 6); // { dg-warning "\\\[-Warray-bounds" }
157 T2 (a3[1].ma3[0].a7, a3[1].ma3[1].a7, 6, 6);
158 T2 (a3[1].ma3[0].a7, a3[1].ma3[2].a7, 6, 6);
159
160 T2 (a3[1].ma3[1].a7, a3[1].ma3[0].a7, 6, 6);
161 T2 (a3[1].ma3[1].a7, a3[1].ma3[1].a7, 6, 6); // { dg-warning "\\\[-Warray-bounds" }
162 T2 (a3[1].ma3[1].a7, a3[1].ma3[2].a7, 6, 6);
163
164 T2 (a3[1].ma3[2].a7, a3[1].ma3[0].a7, 6, 6);
165 T2 (a3[1].ma3[2].a7, a3[1].ma3[1].a7, 6, 6);
166 T2 (a3[1].ma3[2].a7, a3[1].ma3[2].a7, 6, 6); // { dg-warning "\\\[-Warray-bounds" }
167
168 T2 (a3[1].ma3[0].a7, a3[2].ma3[0].a7, 6, 6);
169 T2 (a3[1].ma3[0].a7, a3[2].ma3[1].a7, 6, 6);
170 T2 (a3[1].ma3[0].a7, a3[2].ma3[2].a7, 6, 6);
171
172 T2 (a3[1].ma3[1].a7, a3[2].ma3[0].a7, 6, 6);
173 T2 (a3[1].ma3[1].a7, a3[2].ma3[1].a7, 6, 6);
174 T2 (a3[1].ma3[1].a7, a3[2].ma3[2].a7, 6, 6);
175
176 T2 (a3[1].ma3[2].a7, a3[2].ma3[0].a7, 6, 6);
177 T2 (a3[1].ma3[2].a7, a3[2].ma3[1].a7, 6, 6);
178 T2 (a3[1].ma3[2].a7, a3[2].ma3[2].a7, 6, 6);
179
180
181 T2 (a3[2].ma3[0].a7, a3[0].ma3[0].a7, 6, 6);
182 T2 (a3[2].ma3[0].a7, a3[0].ma3[1].a7, 6, 6);
183 T2 (a3[2].ma3[0].a7, a3[0].ma3[2].a7, 6, 6);
184
185 T2 (a3[2].ma3[1].a7, a3[0].ma3[0].a7, 6, 6);
186 T2 (a3[2].ma3[1].a7, a3[0].ma3[1].a7, 6, 6);
187 T2 (a3[2].ma3[1].a7, a3[0].ma3[2].a7, 6, 6);
188
189 T2 (a3[2].ma3[2].a7, a3[0].ma3[0].a7, 6, 6);
190 T2 (a3[2].ma3[2].a7, a3[0].ma3[1].a7, 6, 6);
191 T2 (a3[2].ma3[2].a7, a3[0].ma3[2].a7, 6, 6);
192
193 T2 (a3[2].ma3[0].a7, a3[1].ma3[0].a7, 6, 6);
194 T2 (a3[2].ma3[0].a7, a3[1].ma3[1].a7, 6, 6);
195 T2 (a3[2].ma3[0].a7, a3[1].ma3[2].a7, 6, 6);
196
197 T2 (a3[2].ma3[1].a7, a3[1].ma3[0].a7, 6, 6);
198 T2 (a3[2].ma3[1].a7, a3[1].ma3[1].a7, 6, 6);
199 T2 (a3[2].ma3[1].a7, a3[1].ma3[2].a7, 6, 6);
200
201 T2 (a3[2].ma3[2].a7, a3[1].ma3[0].a7, 6, 6);
202 T2 (a3[2].ma3[2].a7, a3[1].ma3[1].a7, 6, 6);
203 T2 (a3[2].ma3[2].a7, a3[1].ma3[2].a7, 6, 6);
204
205 T2 (a3[2].ma3[0].a7, a3[2].ma3[0].a7, 6, 6); // { dg-warning "\\\[-Warray-bounds" }
206 T2 (a3[2].ma3[0].a7, a3[2].ma3[1].a7, 6, 6);
207 T2 (a3[2].ma3[0].a7, a3[2].ma3[2].a7, 6, 6);
208
209 T2 (a3[2].ma3[1].a7, a3[2].ma3[0].a7, 6, 6);
210 T2 (a3[2].ma3[1].a7, a3[2].ma3[1].a7, 6, 6); // { dg-warning "\\\[-Warray-bounds" }
211 T2 (a3[2].ma3[1].a7, a3[2].ma3[2].a7, 6, 6);
212
213 T2 (a3[2].ma3[2].a7, a3[2].ma3[0].a7, 6, 6);
214 T2 (a3[2].ma3[2].a7, a3[2].ma3[1].a7, 6, 6);
215 T2 (a3[2].ma3[2].a7, a3[2].ma3[2].a7, 6, 6); // { dg-warning "\\\[-Warray-bounds" }
216 }
217
218
strcat_arrays_of_arrays_ref(struct ArraysOfMemArrays * p)219 void strcat_arrays_of_arrays_ref (struct ArraysOfMemArrays *p)
220 {
221 T2 (p[0].ma3[0].a7, p[0].ma3[0].a7, 6, 6); // { dg-warning "\\\[-Warray-bounds" }
222 T2 (p[0].ma3[0].a7, p[0].ma3[1].a7, 6, 6);
223 T2 (p[0].ma3[0].a7, p[0].ma3[2].a7, 6, 6);
224
225 T2 (p[0].ma3[1].a7, p[0].ma3[0].a7, 6, 6);
226 T2 (p[0].ma3[1].a7, p[0].ma3[1].a7, 6, 6); // { dg-warning "\\\[-Warray-bounds" }
227 T2 (p[0].ma3[1].a7, p[0].ma3[2].a7, 6, 6);
228
229 T2 (p[0].ma3[2].a7, p[0].ma3[0].a7, 6, 6);
230 T2 (p[0].ma3[2].a7, p[0].ma3[1].a7, 6, 6);
231 T2 (p[0].ma3[2].a7, p[0].ma3[2].a7, 6, 6); // { dg-warning "\\\[-Warray-bounds" }
232
233 T2 (p[0].ma3[0].a7, p[1].ma3[0].a7, 6, 6);
234 T2 (p[0].ma3[0].a7, p[1].ma3[1].a7, 6, 6);
235 T2 (p[0].ma3[0].a7, p[1].ma3[2].a7, 6, 6);
236
237 T2 (p[0].ma3[1].a7, p[1].ma3[0].a7, 6, 6);
238 T2 (p[0].ma3[1].a7, p[1].ma3[1].a7, 6, 6);
239 T2 (p[0].ma3[1].a7, p[1].ma3[2].a7, 6, 6);
240
241 T2 (p[0].ma3[2].a7, p[1].ma3[0].a7, 6, 6);
242 T2 (p[0].ma3[2].a7, p[1].ma3[1].a7, 6, 6);
243 T2 (p[0].ma3[2].a7, p[1].ma3[2].a7, 6, 6);
244
245 T2 (p[0].ma3[0].a7, p[2].ma3[0].a7, 6, 6);
246 T2 (p[0].ma3[0].a7, p[2].ma3[1].a7, 6, 6);
247 T2 (p[0].ma3[0].a7, p[2].ma3[2].a7, 6, 6);
248
249 T2 (p[0].ma3[1].a7, p[2].ma3[0].a7, 6, 6);
250 T2 (p[0].ma3[1].a7, p[2].ma3[1].a7, 6, 6);
251 T2 (p[0].ma3[1].a7, p[2].ma3[2].a7, 6, 6);
252
253 T2 (p[0].ma3[2].a7, p[2].ma3[0].a7, 6, 6);
254 T2 (p[0].ma3[2].a7, p[2].ma3[1].a7, 6, 6);
255 T2 (p[0].ma3[2].a7, p[2].ma3[2].a7, 6, 6);
256
257
258 T2 (p[1].ma3[0].a7, p[0].ma3[0].a7, 6, 6);
259 T2 (p[1].ma3[0].a7, p[0].ma3[1].a7, 6, 6);
260 T2 (p[1].ma3[0].a7, p[0].ma3[2].a7, 6, 6);
261
262 T2 (p[1].ma3[1].a7, p[0].ma3[0].a7, 6, 6);
263 T2 (p[1].ma3[1].a7, p[0].ma3[1].a7, 6, 6);
264 T2 (p[1].ma3[1].a7, p[0].ma3[2].a7, 6, 6);
265
266 T2 (p[1].ma3[2].a7, p[0].ma3[0].a7, 6, 6);
267 T2 (p[1].ma3[2].a7, p[0].ma3[1].a7, 6, 6);
268 T2 (p[1].ma3[2].a7, p[0].ma3[2].a7, 6, 6);
269
270 T2 (p[1].ma3[0].a7, p[1].ma3[0].a7, 6, 6); // { dg-warning "\\\[-Warray-bounds" }
271 T2 (p[1].ma3[0].a7, p[1].ma3[1].a7, 6, 6);
272 T2 (p[1].ma3[0].a7, p[1].ma3[2].a7, 6, 6);
273
274 T2 (p[1].ma3[1].a7, p[1].ma3[0].a7, 6, 6);
275 T2 (p[1].ma3[1].a7, p[1].ma3[1].a7, 6, 6); // { dg-warning "\\\[-Warray-bounds" }
276 T2 (p[1].ma3[1].a7, p[1].ma3[2].a7, 6, 6);
277
278 T2 (p[1].ma3[2].a7, p[1].ma3[0].a7, 6, 6);
279 T2 (p[1].ma3[2].a7, p[1].ma3[1].a7, 6, 6);
280 T2 (p[1].ma3[2].a7, p[1].ma3[2].a7, 6, 6); // { dg-warning "\\\[-Warray-bounds" }
281
282 T2 (p[1].ma3[0].a7, p[2].ma3[0].a7, 6, 6);
283 T2 (p[1].ma3[0].a7, p[2].ma3[1].a7, 6, 6);
284 T2 (p[1].ma3[0].a7, p[2].ma3[2].a7, 6, 6);
285
286 T2 (p[1].ma3[1].a7, p[2].ma3[0].a7, 6, 6);
287 T2 (p[1].ma3[1].a7, p[2].ma3[1].a7, 6, 6);
288 T2 (p[1].ma3[1].a7, p[2].ma3[2].a7, 6, 6);
289
290 T2 (p[1].ma3[2].a7, p[2].ma3[0].a7, 6, 6);
291 T2 (p[1].ma3[2].a7, p[2].ma3[1].a7, 6, 6);
292 T2 (p[1].ma3[2].a7, p[2].ma3[2].a7, 6, 6);
293
294
295 T2 (p[2].ma3[0].a7, p[0].ma3[0].a7, 6, 6);
296 T2 (p[2].ma3[0].a7, p[0].ma3[1].a7, 6, 6);
297 T2 (p[2].ma3[0].a7, p[0].ma3[2].a7, 6, 6);
298
299 T2 (p[2].ma3[1].a7, p[0].ma3[0].a7, 6, 6);
300 T2 (p[2].ma3[1].a7, p[0].ma3[1].a7, 6, 6);
301 T2 (p[2].ma3[1].a7, p[0].ma3[2].a7, 6, 6);
302
303 T2 (p[2].ma3[2].a7, p[0].ma3[0].a7, 6, 6);
304 T2 (p[2].ma3[2].a7, p[0].ma3[1].a7, 6, 6);
305 T2 (p[2].ma3[2].a7, p[0].ma3[2].a7, 6, 6);
306
307 T2 (p[2].ma3[0].a7, p[1].ma3[0].a7, 6, 6);
308 T2 (p[2].ma3[0].a7, p[1].ma3[1].a7, 6, 6);
309 T2 (p[2].ma3[0].a7, p[1].ma3[2].a7, 6, 6);
310
311 T2 (p[2].ma3[1].a7, p[1].ma3[0].a7, 6, 6);
312 T2 (p[2].ma3[1].a7, p[1].ma3[1].a7, 6, 6);
313 T2 (p[2].ma3[1].a7, p[1].ma3[2].a7, 6, 6);
314
315 T2 (p[2].ma3[2].a7, p[1].ma3[0].a7, 6, 6);
316 T2 (p[2].ma3[2].a7, p[1].ma3[1].a7, 6, 6);
317 T2 (p[2].ma3[2].a7, p[1].ma3[2].a7, 6, 6);
318
319 T2 (p[2].ma3[0].a7, p[2].ma3[0].a7, 6, 6); // { dg-warning "\\\[-Warray-bounds" }
320 T2 (p[2].ma3[0].a7, p[2].ma3[1].a7, 6, 6);
321 T2 (p[2].ma3[0].a7, p[2].ma3[2].a7, 6, 6);
322
323 T2 (p[2].ma3[1].a7, p[2].ma3[0].a7, 6, 6);
324 T2 (p[2].ma3[1].a7, p[2].ma3[1].a7, 6, 6); // { dg-warning "\\\[-Warray-bounds" }
325 T2 (p[2].ma3[1].a7, p[2].ma3[2].a7, 6, 6);
326
327 T2 (p[2].ma3[2].a7, p[2].ma3[0].a7, 6, 6);
328 T2 (p[2].ma3[2].a7, p[2].ma3[1].a7, 6, 6);
329 T2 (p[2].ma3[2].a7, p[2].ma3[2].a7, 6, 6); // { dg-warning "\\\[-Warray-bounds" }
330 }
331