131
|
1 /* Exercise that -Warray-bounds is issued for out-of-bounds offsets
|
|
2 in calls to built-in functions.
|
|
3 { dg-do compile }
|
|
4 { dg-options "-O2 -Wno-stringop-overflow -Warray-bounds -ftrack-macro-expansion=0" } */
|
|
5
|
|
6 #include "../gcc.dg/range.h"
|
|
7
|
|
8 #if __cplusplus
|
|
9 # define restrict __restrict
|
|
10 extern "C" {
|
|
11 #endif
|
|
12
|
|
13 extern void* memcpy (void* restrict, const void* restrict, size_t);
|
|
14 extern void* mempcpy (void* restrict, const void* restrict, size_t);
|
|
15 extern void* memmove (void*, const void*, size_t);
|
|
16
|
|
17 extern char* stpcpy (char* restrict, const char* restrict);
|
|
18
|
|
19 extern char* strcat (char* restrict, const char* restrict);
|
|
20 extern char* strcpy (char* restrict, const char* restrict);
|
|
21 extern char* strncpy (char* restrict, const char* restrict, size_t);
|
|
22
|
|
23 #if __cplusplus
|
|
24 } /* extern "C" */
|
|
25 #endif
|
|
26
|
|
27 void sink (void*, ...);
|
|
28
|
|
29 #define CAT(x, y) x ## y
|
|
30 #define CONCAT(x, y) CAT (x, y)
|
|
31 #define UNIQUE_NAME(x) CONCAT(x, __LINE__)
|
|
32
|
|
33 #define T(type, N, dst, src, n) do { \
|
|
34 extern type UNIQUE_NAME (a)[N]; \
|
|
35 type *a = UNIQUE_NAME (a); \
|
|
36 type *pd = (dst); \
|
|
37 const type *ps = (src); \
|
|
38 FUNC (pd, ps, n); \
|
|
39 sink (a, pd, ps); \
|
|
40 } while (0)
|
|
41
|
|
42
|
|
43 void test_memcpy_bounds (char *d, const char *s, size_t n)
|
|
44 {
|
|
45 #define FUNC memcpy
|
|
46
|
|
47 /* Verify that invalid offsets into an array of known size are
|
|
48 detected. */
|
|
49
|
|
50 T (char, 1, a + SR (DIFF_MIN, -1), s, n); /* { dg-warning "offset \\\[-\[0-9\]+, -1] is out of the bounds \\\[0, 1] of object \[^\n\r]* with type .char ?\\\[1]" } */
|
|
51 T (char, 1, a + SR (-2, -1), s, n); /* { dg-warning "offset \\\[-2, -1] is out of the bounds \\\[0, 1] of object" } */
|
|
52 T (char, 1, a + SR (-2, 0), s, n);
|
|
53
|
|
54 T (char, 1, a + UR (0, 1), s, n);
|
|
55 T (char, 1, a + UR (0, 2), s, n);
|
|
56 T (char, 1, a + UR (1, 2), s, n);
|
|
57 T (char, 1, a + UR (2, 3), s, n); /* { dg-warning "offset \\\[2, 3] is out of the bounds \\\[0, 1] of object " } */
|
|
58 T (char, 1, a + UR (2, DIFF_MAX), s, n); /* { dg-warning "offset \\\[2, \[0-9\]+] is out of the bounds \\\[0, 1] of object " "memcpy" } */
|
|
59
|
|
60 /* Offsets in excess of DIFF_MAX are treated as negative even if
|
|
61 they appear as large positive in the source. It would be nice
|
|
62 if they retained their type but unfortunately that's not how
|
|
63 it works so be prepared for both in case it even gets fixed. */
|
|
64 T (char, 1, a + UR (3, SIZE_MAX - 1), s, n); /* { dg-warning "offset \\\[3, -?\[0-9\]+] is out of the bounds \\\[0, 1] of object" "memcpy" } */
|
|
65
|
|
66 /* Verify that invalid offsets into an array of unknown size are
|
|
67 detected. */
|
|
68 extern char arr[];
|
|
69 T (char, 1, arr + SR (DIFF_MIN, 0), s, n);
|
|
70 T (char, 1, arr + SR (DIFF_MIN + 1, -1), s, n); /* { dg-warning "offset \\\[-\[0-9\]+, -1] is out of the bounds of object " "memcpy" } */
|
|
71 T (char, 1, arr + SR (DIFF_MIN, 1), s, n);
|
|
72 T (char, 1, arr + SR (DIFF_MIN, DIFF_MAX), s, n);
|
|
73 T (char, 1, arr + SR ( -2, -1), s, n); /* { dg-warning "offset \\\[-2, -1] is out of the bounds of object " "memcpy" } */
|
|
74 T (char, 1, arr + SR ( -1, 0), s, n);
|
|
75 T (char, 1, arr + SR ( -1, 1), s, n);
|
|
76 T (char, 1, arr + SR ( -1, DIFF_MAX - 1), s, n);
|
|
77 T (char, 1, arr + SR ( 0, 1), s, n);
|
|
78 T (char, 1, arr + SR ( 0, DIFF_MAX - 1), s, n);
|
|
79 T (char, 1, arr + SR ( 1, 2), s, n);
|
|
80 T (char, 1, arr + SR ( 1, DIFF_MAX - 1), s, n);
|
|
81
|
|
82 /* Verify that all offsets via a pointer to an uknown object are
|
|
83 accepted. */
|
|
84
|
|
85 /* Negative indices between [DIFF_MIN, DIFF_MAX] are valid since
|
|
86 the pointer to which the offset is applied can be at a positive
|
|
87 offset from the beginning of an object. */
|
|
88 T (char, 1, d + SR (DIFF_MIN, 0), s, n);
|
|
89 T (char, 1, d + SR (DIFF_MIN, -1), s, n);
|
|
90 T (char, 1, d + SR (DIFF_MIN, 1), s, n);
|
|
91 T (char, 1, d + SR (DIFF_MIN, DIFF_MAX - 1), s, n);
|
|
92 T (char, 1, d + SR ( -2, -1), s, n);
|
|
93 T (char, 1, d + SR ( -1, 0), s, n);
|
|
94 T (char, 1, d + SR ( -1, 1), s, n);
|
|
95 T (char, 1, d + SR ( -1, DIFF_MAX - 1), s, n);
|
|
96 T (char, 1, d + SR ( 0, 1), s, n);
|
|
97 T (char, 1, d + SR ( 0, DIFF_MAX - 1), s, n);
|
|
98 T (char, 1, d + SR ( 1, 2), s, n);
|
|
99 T (char, 1, d + SR ( 1, DIFF_MAX - 1), s, n);
|
|
100 }
|
|
101
|
|
102 /* Verify offsets in an anti-range. */
|
|
103
|
|
104 void test_memcpy_bounds_anti_range (char *d, const char *s, size_t n)
|
|
105 {
|
|
106 T (char, 9, a, a + SAR (-2, -1), 3);
|
|
107 T (char, 9, a, a + SAR (-1, 1), 3);
|
|
108 T (char, 9, a, a + SAR ( 0, 1), 3);
|
|
109 T (char, 9, a, a + SAR ( 0, 2), 3);
|
|
110 T (char, 9, a, a + SAR ( 0, 3), 3);
|
|
111 T (char, 9, a, a + SAR ( 0, 4), 3);
|
|
112 T (char, 9, a, a + SAR ( 0, 5), 3);
|
|
113 /* The initial source range is valid but the final range after the access
|
|
114 has complete cannot be. The value mentioned in the warning is the final
|
|
115 offset, i.e., 7 + 3. Including the whole final range because would be
|
|
116 confusing (the upper bound would either be negative or a very large
|
|
117 positive number) so only the lower bound is included. */
|
|
118 T (char, 9, a, a + SAR ( 0, 6), 3); /* { dg-warning "forming offset 10 is out of the bounds \\\[0, 9] of object " "memcpy" } */
|
|
119
|
|
120 /* This fails because the offset isn't represented as an SSA_NAME
|
|
121 but rather as a GIMPLE_PHI (offset, 0). With some effort it is
|
|
122 possible to extract the range from the PHI but it's not implemented
|
|
123 (yet). */
|
|
124 T (char, 9, a, a + SAR ( 1, 6), 3); /* { dg-warning "forming offset \\\[9, 0] is out of the bounds \\\[0, 9] of object " "memcpy" { xfail *-*-* } } */
|
|
125
|
|
126 /* The range of offsets is the union of [0, 1] and [7, PTRDIFF_MAX]
|
|
127 of which the first subrange is valid and thus no warming for memcpy
|
|
128 is issued. Similarly for the next test. */
|
|
129 T (char, 9, a, a + SAR ( 2, 6), 3);
|
|
130 T (char, 9, a, a + SAR ( 3, 6), 3);
|
|
131
|
|
132 T (char, 9, a, a + SAR (-1, 7), 3); /* { dg-warning "forming offset \\\[10, 11] is out of the bounds \\\[0, 9] of object " "memcpy" } */
|
|
133 T (char, 9, a, a + SAR (-2, 8), 3); /* { dg-warning "forming offset \\\[10, 12] is out of the bounds \\\[0, 9] of object " "memcpy" } */
|
|
134 T (char, 9, a, a + SAR (-3, 7), 5); /* { dg-warning "forming offset \\\[10, 13] is out of the bounds \\\[0, 9] of object " "memcpy" } */
|
|
135
|
|
136 T (char, 9, a + SAR (-2, -1), a, 3);
|
|
137 T (char, 9, a + SAR (-1, 1), a, 3);
|
|
138 T (char, 9, a + SAR ( 0, 1), a, 3);
|
|
139 T (char, 9, a + SAR ( 0, 2), a, 3);
|
|
140 T (char, 9, a + SAR ( 0, 3), a, 3);
|
|
141 T (char, 9, a + SAR ( 0, 6), a, 3); /* { dg-warning "forming offset 10 is out of the bounds \\\[0, 9] of object " "memcpy" } */
|
|
142 T (char, 9, a + SAR (-1, 7), a, 3); /* { dg-warning "forming offset \\\[10, 11] is out of the bounds \\\[0, 9] of object " "memcpy" } */
|
|
143 T (char, 9, a + SAR (-2, 8), a, 3); /* { dg-warning "forming offset \\\[10, 12] is out of the bounds \\\[0, 9] of object " "memcpy" } */
|
|
144
|
|
145 ptrdiff_t i = SAR (DIFF_MIN + 1, DIFF_MAX - 4);
|
|
146 T (char, 1, d, d + SAR (DIFF_MIN + 3, DIFF_MAX - 1), 3);
|
|
147 T (char, 1, d, d + SAR (DIFF_MIN + 3, DIFF_MAX - 3), 5);
|
|
148 }
|
|
149
|
|
150 /* Verify that pointer overflow in the computation done by memcpy
|
|
151 (i.e., offset + size) is detected and diagnosed. */
|
|
152
|
|
153 void test_memcpy_overflow (char *d, const char *s, size_t n)
|
|
154 {
|
|
155 extern char arr[];
|
|
156
|
|
157 /* Verify that offset overflow involving an array of unknown size
|
|
158 but known access size is detected. This works except with small
|
|
159 sizes that are powers of 2 due to bug . */
|
|
160 T (char, 1, arr + SR (DIFF_MAX - 1, DIFF_MAX), s, 1);
|
|
161 T (char, 1, arr + SR (DIFF_MAX - 1, DIFF_MAX), s, 2); /* { dg-warning "pointer overflow between offset \\\[\[0-9\]+, \[0-9\]+] and size 2 accessing array " "bug " { xfail *-*-* } } */
|
|
162 T (char, 1, arr + SR (DIFF_MAX - 2, DIFF_MAX), s, 3); /* { dg-warning "pointer overflow between offset \\\[\[0-9\]+, \[0-9\]+] and size 3 accessing array " "memcpy" } */
|
|
163 T (char, 1, arr + SR (DIFF_MAX - 4, DIFF_MAX), s, 5); /* { dg-warning "pointer overflow between offset \\\[\[0-9\]+, \[0-9\]+] and size 5 accessing array " "memcpy" } */
|
|
164 }
|
|
165
|
|
166 void test_memcpy_bounds_memarray_range (void)
|
|
167 {
|
|
168 #undef TM
|
|
169 #define TM(mem, dst, src, n) \
|
|
170 do { \
|
|
171 struct MA { char a5[5]; int i; } ma; \
|
|
172 sink (&ma); /* Initialize arrays. */ \
|
|
173 memcpy (dst, src, n); \
|
|
174 sink (&ma); \
|
|
175 } while (0)
|
|
176
|
|
177 ptrdiff_t i = SR (1, 2);
|
|
178
|
|
179 TM (ma.a5, ma.a5 + i, ma.a5, 1);
|
|
180 TM (ma.a5, ma.a5 + i, ma.a5, 3);
|
|
181 TM (ma.a5, ma.a5 + i, ma.a5, 5);
|
|
182 TM (ma.a5, ma.a5 + i, ma.a5, 7); /* diagnosed with -Warray-bounds=2 */
|
|
183 }
|
|
184
|
|
185 void test_memmove_bounds (char *d, const char *s, size_t n)
|
|
186 {
|
|
187 #undef FUNC
|
|
188 #define FUNC memmove
|
|
189
|
|
190 T (char, 1, a + SR (DIFF_MIN + 1, -1), s, n); /* { dg-warning "offset \\\[-\[0-9\]+, -1] is out of the bounds \\\[0, 1] of object \[^\n\r]+ with type .char ?\\\[1]" } */
|
|
191 T (char, 1, a + SR (-2, -1), s, n); /* { dg-warning "offset \\\[-2, -1] is out of the bounds \\\[0, 1] of object" } */
|
|
192 T (char, 1, a + SR (-2, 0), s, n);
|
|
193
|
|
194 const int *pi = (const int*)s;
|
|
195 T (int, 2, a + SR (-1, 1), pi, n);
|
|
196 T (int, 2, a + SR (-1, 2), pi, n);
|
|
197 T (int, 2, a + SR ( 0, 2), pi, n);
|
|
198 T (int, 2, a + SR ( 0, 3), pi, n);
|
|
199 T (int, 2, a + SR ( 1, 3), pi, n);
|
|
200 T (int, 2, a + SR ( 2, 3), pi, n);
|
|
201
|
|
202 const int32_t *pi32 = (const int32_t*)s;
|
|
203 T (int32_t, 2, a + SR ( 3, 4), pi32, n); /* { dg-warning "offset \\\[12, 16] is out of the bounds \\\[0, 8] of object .\[^\n\r]+. with type .int32_t ?\\\[2]." } */
|
|
204 }
|
|
205
|
|
206
|
|
207 void test_mempcpy_bounds (char *d, const char *s, size_t n)
|
|
208 {
|
|
209 #undef FUNC
|
|
210 #define FUNC mempcpy
|
|
211
|
|
212 /* Verify that invalid offsets into an array of known size are
|
|
213 detected. */
|
|
214
|
|
215 T (char, 1, a + SR (DIFF_MIN, -1), s, n); /* { dg-warning "offset \\\[-\[0-9\]+, -1] is out of the bounds" "mempcpy" } */
|
|
216 T (char, 1, a + SR (-2, -1), s, n); /* { dg-warning "offset \\\[-2, -1] is out of the bounds" "mempcpy" } */
|
|
217 T (char, 1, a + SR (-2, 0), s, n);
|
|
218
|
|
219 T (char, 1, a + UR (0, 1), s, n);
|
|
220 T (char, 1, a + UR (0, 2), s, n);
|
|
221 T (char, 1, a + UR (1, 2), s, n);
|
|
222 T (char, 1, a + UR (2, 3), s, n); /* { dg-warning "offset \\\[2, 3] is out of the bounds \\\[0, 1] of object " "mempcpy" } */
|
|
223 T (char, 1, a + UR (2, DIFF_MAX), s, n); /* { dg-warning "offset \\\[2, \[0-9\]+] is out of the bounds \\\[0, 1] of object" "mempcpy" } */
|
|
224
|
|
225 /* Offsets in excess of DIFF_MAX are treated as negative even if
|
|
226 they appear as large positive in the source. It would be nice
|
|
227 if they retained their type but unfortunately that's not how
|
|
228 it works so be prepared for both in case it ever gets fixed. */
|
|
229 T (char, 1, a + UR (3, SIZE_MAX), s, n); /* { dg-warning "offset \\\[3, -?\[0-9\]+] is out of the bounds \\\[0, 1] of object " "mempcpy" } */
|
|
230
|
|
231 /* Verify that invalid offsets into an array of unknown size are
|
|
232 detected. */
|
|
233 extern char arr[];
|
|
234 T (char, 1, arr + SR (DIFF_MIN, 0), s, n);
|
|
235 T (char, 1, arr + SR (DIFF_MIN, -1), s, n); /* { dg-warning "offset \\\[-\[0-9\]+, -1] is out of the bounds of object" "mempcpy" } */
|
|
236 T (char, 1, arr + SR (DIFF_MIN, 1), s, n);
|
|
237 T (char, 1, arr + SR (DIFF_MIN, DIFF_MAX), s, n);
|
|
238 T (char, 1, arr + SR ( -2, -1), s, n); /* { dg-warning "offset \\\[-2, -1] is out of the bounds of object" "mempcpy" } */
|
|
239 T (char, 1, arr + SR ( -1, 0), s, n);
|
|
240 T (char, 1, arr + SR ( -1, 1), s, n);
|
|
241 T (char, 1, arr + SR ( -1, DIFF_MAX), s, n);
|
|
242 T (char, 1, arr + SR ( 0, 1), s, n);
|
|
243 T (char, 1, arr + SR ( 0, DIFF_MAX), s, n);
|
|
244 T (char, 1, arr + SR ( 1, 2), s, n);
|
|
245 T (char, 1, arr + SR ( 1, DIFF_MAX), s, n);
|
|
246
|
|
247 /* Verify that all offsets via a pointer to an uknown object are
|
|
248 accepted. */
|
|
249
|
|
250 /* Negative indices between [DIFF_MIN, DIFF_MAX] are valid since
|
|
251 the pointer to which the offset is applied can be at a positive
|
|
252 offset from the beginning of an object. */
|
|
253 T (char, 1, d + SR (DIFF_MIN, 0), s, n);
|
|
254 T (char, 1, d + SR (DIFF_MIN, -1), s, n);
|
|
255 T (char, 1, d + SR (DIFF_MIN, 1), s, n);
|
|
256 T (char, 1, d + SR (DIFF_MIN, DIFF_MAX), s, n);
|
|
257 T (char, 1, d + SR ( -2, -1), s, n);
|
|
258 T (char, 1, d + SR ( -1, 0), s, n);
|
|
259 T (char, 1, d + SR ( -1, 1), s, n);
|
|
260 T (char, 1, d + SR ( -1, DIFF_MAX), s, n);
|
|
261 T (char, 1, d + SR ( 0, 1), s, n);
|
|
262 T (char, 1, d + SR ( 0, DIFF_MAX), s, n);
|
|
263 T (char, 1, d + SR ( 1, 2), s, n);
|
|
264 T (char, 1, d + SR ( 1, DIFF_MAX), s, n);
|
|
265 }
|
|
266
|
|
267 #define TI(type, N, init, dst, src) do { \
|
|
268 type UNIQUE_NAME (a)[N] = init; \
|
|
269 type *a = UNIQUE_NAME (a); \
|
|
270 type *pd = (dst); \
|
|
271 const type *ps = (src); \
|
|
272 FUNC (pd, ps); \
|
|
273 sink (a, pd, ps, s); \
|
|
274 } while (0)
|
|
275
|
|
276 void test_strcpy_bounds (char *d, const char *s)
|
|
277 {
|
|
278 #undef FUNC
|
|
279 #define FUNC strcpy
|
|
280
|
|
281 ptrdiff_t i;
|
|
282
|
|
283 TI (char, 1, "", a, a + SR (DIFF_MIN, 0));
|
|
284 TI (char, 1, "", a, a + SR (-1, 0));
|
|
285 TI (char, 1, "", a, a + SR (-1, 1));
|
|
286 TI (char, 1, "", a, a + SR (0, 1));
|
|
287 TI (char, 1, "", a, a + SR (0, DIFF_MAX - 1));
|
|
288 TI (char, 2, "0", a, a + SR (0, DIFF_MAX - 1));
|
|
289 TI (char, 2, "0", a, a + SR (1, DIFF_MAX - 1));
|
|
290 /* The following needs a warning for reading past the end. */
|
|
291 TI (char, 2, "0", a, a + SR (2, DIFF_MAX - 1));
|
|
292 TI (char, 2, "0", a, a + SR (3, DIFF_MAX - 1)); /* { dg-warning "offset \\\[3, \[0-9\]+] is out of the bounds \\\[0, 2] of object \[^\n\r\]+ with type .char ?\\\[2\\\]." "strcpy" } */
|
|
293
|
|
294 TI (char, 3, "01", a, a + SR (0, DIFF_MAX - 1));
|
|
295 TI (char, 3, "01", a, a + SR (1, DIFF_MAX - 1));
|
|
296 TI (char, 3, "01", a, a + SR (2, DIFF_MAX - 1));
|
|
297 /* The following needs a warning for reading past the end. */
|
|
298 TI (char, 3, "01", a, a + SR (3, DIFF_MAX - 1));
|
|
299 TI (char, 3, "01", a, a + SR (4, DIFF_MAX - 1)); /* { dg-warning "offset \\\[4, \[0-9\]+] is out of the bounds \\\[0, 3] of object \[^\n\r\]+ with type .char ?\\\[3\\\]." "strcpy" } */
|
|
300
|
|
301 TI (char, 4, "012", a, a + SR (DIFF_MAX - 2, DIFF_MAX - 1)); /* { dg-warning "offset \\\[\[0-9\]+, \[0-9\]+] is out of the bounds \\\[0, 4] of object \[^\n\r\]+ with type .char ?\\\[4\\\]." "strcpy" } */
|
|
302
|
|
303
|
|
304 TI (char, 1, "", a + SR (DIFF_MIN, 0), s);
|
|
305 TI (char, 1, "", a + SR (-1, 0), s);
|
|
306 TI (char, 1, "", a + SR (-1, 1), s);
|
|
307 TI (char, 1, "", a + SR (0, 1), s);
|
|
308 TI (char, 1, "", a + SR (0, DIFF_MAX - 1), s);
|
|
309 TI (char, 2, "", a + SR (0, DIFF_MAX - 1), s);
|
|
310 TI (char, 2, "", a + SR (1, DIFF_MAX - 1), s);
|
|
311 /* The following is diagnosed not because the initial source offset
|
|
312 it out of bounds (it isn't) but because the final source offset
|
|
313 after the access has completed, is. It would be clearer if
|
|
314 the warning mentioned the final offset. */
|
|
315 TI (char, 2, "", a + SR (2, DIFF_MAX - 1), s); /* { dg-warning "forming offset 3 is out of the bounds \\\[0, 2] of object \[^\n\r\]+ with type .char ?\\\[2\\\]." "strcpy" } */
|
|
316 TI (char, 2, "", a + SR (3, DIFF_MAX - 1), s); /* { dg-warning "offset \\\[3, \[0-9\]+] is out of the bounds \\\[0, 2] of object \[^\n\r\]+ with type .char ?\\\[2\\\]." "strcpy" } */
|
|
317
|
|
318 TI (char, 3, "", a + SR (0, DIFF_MAX - 1), s);
|
|
319 TI (char, 3, "", a + SR (1, DIFF_MAX - 1), s);
|
|
320 TI (char, 3, "", a + SR (2, DIFF_MAX - 1), s);
|
|
321 TI (char, 3, "", a + SR (3, DIFF_MAX - 1), s); /* { dg-warning "forming offset 4 is out of the bounds \\\[0, 3] of object \[^\n\r\]+ with type .char ?\\\[3\\\]." "strcpy" } */
|
|
322 TI (char, 3, "", a + SR (4, DIFF_MAX - 1), s); /* { dg-warning "offset \\\[4, \[0-9\]+] is out of the bounds \\\[0, 3] of object \[^\n\r\]+ with type .char ?\\\[3\\\]." "strcpy" } */
|
|
323
|
|
324 TI (char, 4, "", a + SR (DIFF_MAX - 2, DIFF_MAX - 1), s); /* { dg-warning "offset \\\[\[0-9\]+, \[0-9\]+] is out of the bounds \\\[0, 4] of object \[^\n\r\]+ with type .char ?\\\[4\\\]." "strcpy" } */
|
|
325 }
|
|
326
|
|
327 struct MA
|
|
328 {
|
|
329 int i;
|
|
330 char a5[5];
|
|
331 char a11[11];
|
|
332 };
|
|
333
|
|
334 struct MA2
|
|
335 {
|
|
336 struct MA ma3[3];
|
|
337 struct MA ma5[5];
|
|
338 char ax[];
|
|
339 };
|
|
340
|
|
341 struct MA3
|
|
342 {
|
|
343 struct MA2 ma5[3];
|
|
344 struct MA2 ma7[7];
|
|
345 };
|
|
346
|
|
347 void test_strcpy_bounds_memarray_range (void)
|
|
348 {
|
|
349 #undef TM
|
|
350 #define TM(mem, init, dst, src) \
|
|
351 do { \
|
|
352 struct MA ma; \
|
|
353 strcpy (ma.mem, init); \
|
|
354 strcpy (dst, src); \
|
|
355 sink (&ma); \
|
|
356 } while (0)
|
|
357
|
|
358 ptrdiff_t i = SR (1, 2);
|
|
359
|
|
360 TM (a5, "0", ma.a5 + i, ma.a5);
|
|
361 TM (a5, "01", ma.a5 + i, ma.a5);
|
|
362 TM (a5, "012", ma.a5 + i, ma.a5);
|
|
363 TM (a5, "0123", ma.a5 + i, ma.a5); /* { dg-warning "offset 10 from the object at .ma. is out of the bounds of referenced subobject .\(MA::\)?a5. with type .char ?\\\[5]. at offset 4" "strcpy" } */
|
|
364
|
|
365 TM (a11, "0", ma.a5, ma.a11);
|
|
366 TM (a11, "01", ma.a5, ma.a11);
|
|
367 TM (a11, "012", ma.a5, ma.a11);
|
|
368 TM (a11, "0123", ma.a5, ma.a11);
|
|
369 TM (a11, "01234", ma.a5, ma.a11); /* { dg-warning "offset 10 from the object at .ma. is out of the bounds of referenced subobject .\(MA::\)?a5. with type .char ?\\\[5]' at offset 4" } */
|
|
370 TM (a11, "012345", ma.a5, ma.a11); /* { dg-warning "offset \\\[10, 11] from the object at .ma. is out of the bounds of referenced subobject .\(MA::\)?a5. with type .char ?\\\[5]' at offset 4" } */
|
|
371 TM (a11, "0123456", ma.a5, ma.a11); /* { dg-warning "offset \\\[10, 12] from the object at .ma. is out of the bounds of referenced subobject .\(MA::\)?a5. with type .char ?\\\[5]' at offset 4" } */
|
|
372
|
|
373 TM (a11, "0123456", ma.a11 + i, "789abcd");
|
|
374 }
|
|
375
|
|
376 void test_strcpy_bounds_memarray_var (struct MA *pma,
|
|
377 struct MA2 *pma2,
|
|
378 struct MA3 *pma3,
|
|
379 const char *s, size_t n)
|
|
380 {
|
|
381 #undef TM
|
|
382 #define TM(dst, src) do { \
|
|
383 strcpy (dst, src); \
|
|
384 sink (dst, src); \
|
|
385 } while (0)
|
|
386
|
|
387 TM (pma->a5, s);
|
|
388 TM (pma->a5 + 0, s);
|
|
389 TM (pma->a5 + 1, s);
|
|
390 TM (pma->a5 + 4, s);
|
|
391
|
|
392 /* The following forms a pointer during the call that's outside
|
|
393 the bounds of the array it was derived from (pma->a5) so
|
|
394 it should be diagnosed but the representation of the pointer
|
|
395 addition doesn't contain information to distinguish it from
|
|
396 the valid pma->a11 + 1 so this is an XFAIL. */
|
|
397 TM (pma->a5 + 5, s); /* { dg-warning "offset 17 from the object at .pma. is out of the bounds of .struct MA." "strcpy" { xfail *-*-* } } */
|
|
398
|
|
399 /* The following also forms an out-of-bounds pointer but similar
|
|
400 to the above, there is no reliable way to distinguish it from
|
|
401 (char*)&pma[1].i + 1 so this too is not diagnosed. */
|
|
402 TM (pma->a5 + sizeof *pma + 1, s); /* { dg-warning "offset 17 from the object at .pma. is out of the bounds of .struct MA." "strcpy" { xfail *-*-* } } */
|
|
403
|
|
404 TM (pma->a5 - 1, s); /* { dg-warning "offset -1 from the object at .pma. is out of the bounds of .struct MA." "strcpy" { xfail *-*-* } } */
|
|
405
|
|
406 TM (pma[1].a5, s);
|
|
407 TM (pma[2].a5 + 0, s);
|
|
408 TM (pma[3].a5 + 1, s);
|
|
409 TM (pma[4].a5 + 4, s);
|
|
410
|
|
411
|
|
412 extern struct MA3 ma3[3];
|
|
413 TM (ma3[0].ma5[0].ma3[0].a5 + 6, s);
|
|
414 }
|