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