1 /* Test to exercise that -Warray-bounds warnings for memory and string
2 functions are issued even when they are declared in system headers
3 (i.e., not just when they are explicitly declared in the source
4 file.)
5 Also verify that the warnings are issued even for calls where the
6 source of the excessive array bound is in a different function than
7 the call.
8 { dg-do compile }
9 { dg-options "-O2 -Warray-bounds -Wno-stringop-overflow -fno-tree-vrp" } */
10
11 #if __has_include (<stddef.h>)
12 # include <stddef.h>
13 #else
14 /* For cross-compilers. */
15 typedef __PTRDIFF_TYPE__ ptrdiff_t;
16 typedef __SIZE_TYPE__ size_t;
17 #endif
18
19 #if __has_include (<string.h>)
20 # include <string.h>
21 # undef memcpy
22 # undef strcat
23 # undef strcpy
24 # undef strncpy
25 #else
26 extern void* memcpy (void*, const void*, size_t);
27 extern char* strcat (char*, const char*);
28 extern char* strcpy (char*, const char*);
29 extern char* strncpy (char*, const char*, size_t);
30 #endif
31
32
33 #define MAX (__SIZE_MAX__ / 2)
34
35 void sink (void*);
36
37 struct __attribute__ ((packed)) Array
38 {
39 char a13[13];
40 char a15[15];
41 char a17[17];
42 };
43
44 /* Exercise memcpy out-of-bounds offsets with an array of known size. */
45
46 static void
47 wrap_memcpy_src_xsize (char *d, const char *s, ptrdiff_t i, size_t n)
48 {
49 memcpy (d, s + i, n); /* { dg-warning "offset 46 is out of the bounds \\\[0, 45] of object .ar. with type .(struct )?Array." "memcpy" } */
50 }
51
52 void call_memcpy_src_xsize (char *d, size_t n)
53 {
54 struct Array ar;
55 sink (&ar);
56 wrap_memcpy_src_xsize (d, ar.a13, 46, n);
57 sink (&ar);
58 }
59
60 /* Exercise memcpy out-of-bounds offsets with an array of unknown size. */
61
62 static void
63 wrap_memcpy_src_diff_max (char *d, const char *s, ptrdiff_t i, size_t n)
64 {
65 memcpy (d, s + i, n); /* { dg-warning "pointer overflow between offset \[0-9\]+ and size 3" "memcpy" } */
66 }
67
68 void call_memcpy_src_diff_max (char *d, const char *s, size_t n)
69 {
70 wrap_memcpy_src_diff_max (d, s, MAX, 3);
71 }
72
73 static void
74 wrap_memcpy_dst_xsize (char *d, const char *s, ptrdiff_t i, size_t n)
75 {
76 memcpy (d + i, s, n); /* { dg-warning "offset 47 is out of the bounds \\\[0, 45] of object .ar1. with type .(struct )?Array." "memcpy" } */
77 }
78
79 void call_memcpy_dst_xsize (const char *s, size_t n)
80 {
81 struct Array ar1; /* { dg-message ".ar1. declared here" } */
82 sink (&ar1);
83 wrap_memcpy_dst_xsize (ar1.a15, s, 34, n);
84 sink (&ar1);
85 }
86
87 static void
88 wrap_memcpy_dst_diff_max (char *d, const char *s, ptrdiff_t i, size_t n)
89 {
90 memcpy (d + i, s, n); /* { dg-warning "offset -?\[0-9\]+ is out of the bounds \\\[0, 45] of object .ar2. with type .(struct )?Array." "memcpy" } */
91 }
92
93 void call_memcpy_dst_diff_max (const char *s, size_t n)
94 {
95 struct Array ar2; /* { dg-message ".ar2. declared here" } */
96 sink (&ar2);
97 wrap_memcpy_dst_diff_max (ar2.a15, s, MAX, n);
98 sink (&ar2);
99 }
100
101
102 static void wrap_strcat_src_xsize (char *d, const char *s, ptrdiff_t i)
103 {
104 strcat (d, s + i); /* { dg-warning "offset 46 is out of the bounds \\\[0, 45] of object .ar3. with type .(struct )?Array." "strcat" } */
105 }
106
107 void call_strcat_src_xsize (char *d)
108 {
109 struct Array ar3; /* { dg-message ".ar3. declared here" } */
110 sink (&ar3);
111 wrap_strcat_src_xsize (d, ar3.a15, 15 + 17 + 1);
112 sink (&ar3);
113 }
114
115 static void wrap_strcat_dst_xsize (char *d, const char *s, ptrdiff_t i)
116 {
117 strcat (d + i, s); /* { dg-warning "offset 47 is out of the bounds \\\[0, 45] of object .ar4. with type .(struct )?Array." "strcat" } */
118 }
119
120 void call_strcat_dst_xsize (const char *s)
121 {
122 struct Array ar4; /* { dg-message ".ar4. declared here" } */
123 sink (&ar4);
124 wrap_strcat_dst_xsize (ar4.a15, s, 15 + 17 + 2);
125 sink (&ar4);
126 }
127
128
129 static void wrap_strcpy_src_xsize (char *d, const char *s, ptrdiff_t i)
130 {
131 strcpy (d, s + i); /* { dg-warning "offset 48 is out of the bounds \\\[0, 45] of object .ar5. with type .(struct )?Array." "strcpy" } */
132 }
133
134 void call_strcpy_src_xsize (char *d)
135 {
136 struct Array ar5; /* { dg-message ".ar5. declared here" } */
137 sink (&ar5);
138 wrap_strcpy_src_xsize (d, ar5.a15, 15 + 17 + 3);
139 sink (&ar5);
140 }
141
142 static void wrap_strcpy_dst_xsize (char *d, const char *s, ptrdiff_t i)
143 {
144 strcpy (d + i, s); /* { dg-warning "offset 49 is out of the bounds \\\[0, 45] of object .ar6. with type .(struct )?Array." "strcpy" } */
145 }
146
147 void call_strcpy_dst_xsize (const char *s)
148 {
149 struct Array ar6; /* { dg-message ".ar6. declared here" } */
150 sink (&ar6);
151 wrap_strcpy_dst_xsize (ar6.a15, s, 15 + 17 + 4);
152 sink (&ar6);
153 }
154
155
156 /* Exercise strncpy out-of-bounds offsets with an array of known size. */
157
158 static void
159 wrap_strncpy_src_xsize (char *d, const char *s, ptrdiff_t i, size_t n)
160 {
161 strncpy (d, s + i, n); /* { dg-warning "offset 46 is out of the bounds \\\[0, 45] of object .ar7. with type '(struct )?Array." "strncpy" } */
162 }
163
164 void call_strncpy_src_xsize (char *d, size_t n)
165 {
166 struct Array ar7; /* { dg-message ".ar7. declared here" } */
167 sink (&ar7);
168 wrap_strncpy_src_xsize (d, ar7.a17, 17 + 1, n);
169 sink (&ar7);
170 }
171
172 /* Exercise strncpy out-of-bounds offsets with an array of unknown size. */
173
174 static void
175 wrap_strncpy_src_diff_max_m1 (char *d, const char *s, ptrdiff_t i, size_t n)
176 {
177 /* Unlike in the similar call to memcpy(), there is no pointer
178 overflow here because the size N is not added to the source
179 offset MAX - 1 (only 1 is for the access to its first element,
180 which is tested below). */
181 strncpy (d, s + i, n);
182 }
183
184 void call_strncpy_src_diff_max_m1 (char *d, const char *s, size_t n)
185 {
186 wrap_strncpy_src_diff_max_m1 (d, s, MAX - 1, 3);
187 }
188
189 static void
190 wrap_strncpy_src_diff_max (char *d, const char *s, ptrdiff_t i, size_t n)
191 {
192 strncpy (d, s + i, n); /* { dg-warning "pointer overflow between offset \[0-9\]+ and size \\\[1, 0]" } */
193 }
194
195 void call_strncpy_src_diff_max (char *d, const char *s, size_t n)
196 {
197 wrap_strncpy_src_diff_max (d, s, MAX, 3);
198 }
199
200 static void
201 wrap_strncpy_dst_xsize (char *d, const char *s, ptrdiff_t i, size_t n)
202 {
203 strncpy (d + i, s, n); /* { dg-warning "offset 47 is out of the bounds \\\[0, 45] of object .ar8. with type .(struct )?Array." "strncpy" } */
204 }
205
206 void call_strncpy_dst_xsize (const char *s, size_t n)
207 {
208 struct Array ar8; /* { dg-message ".ar8. declared here" } */
209 sink (&ar8);
210 wrap_strncpy_dst_xsize (ar8.a17, s, 17 + 2, n);
211 sink (&ar8);
212 }
213
214 static void
215 wrap_strncpy_dst_diff_max (char *d, const char *s, ptrdiff_t i, size_t n)
216 {
217 strncpy (d + i, s, n); /* { dg-warning "offset -\[0-9\]+ is out of the bounds \\\[0, 45] of object .ar9. with type .(struct )?Array." "strncpy" } */
218 }
219
220 void call_strncpy_dst_diff_max (const char *s, size_t n)
221 {
222 struct Array ar9; /* { dg-message ".ar9. declared here" "strncpy" } */
223 sink (&ar9);
224 wrap_strncpy_dst_diff_max (ar9.a17, s, MAX, n);
225 sink (&ar9);
226 }
227
228 static void
229 wrap_strncpy_dstarray_diff_neg (char *d, const char *s, ptrdiff_t i, size_t n)
230 {
231 strncpy (d + i, s, n); /* { dg-warning "offset -\[0-9\]+ is out of the bounds \\\[0, 90] of object .ar10. with type .(struct )?Array ?\\\[2]." "strncpy" } */
232 }
233
234 void call_strncpy_dstarray_diff_neg (const char *s, size_t n)
235 {
236 struct Array ar10[2]; /* { dg-message ".ar10. declared here" } */
237 sink (&ar10);
238
239 int off = (char*)ar10[1].a17 - (char*)ar10 + 1;
240 wrap_strncpy_dstarray_diff_neg (ar10[1].a17, s, -off, n);
241
242 sink (&ar10);
243 }