1 /* PR middle-end/97023 - missing warning on buffer overflow in chained mempcpy
2 Verify that out of bounds writes by built-ins to objects through pointers
3 returned by other built-ins are diagnosed.
4 { dg-do compile }
5 { dg-options "-O2" } */
6
7 #include "range.h"
8
9 void* malloc (size_t);
10 void* memcpy (void*, const void*, size_t);
11 void* memmove (void*, const void*, size_t);
12 void* mempcpy (void*, const void*, size_t);
13
14 void sink (void*, ...);
15
16
17 void nowarn_memcpy (const void *s)
18 {
19 extern char cpy_a4[4];
20 unsigned n = sizeof cpy_a4;
21
22 void *p = cpy_a4;
23 p = memcpy (p, s, n);
24 sink (p);
25 memcpy (p, s, n);
26 sink (p);
27
28 p = cpy_a4 + 1;
29 p = memcpy (p, s, n - 1);
30 sink (p);
31 memcpy (p, s, n - 1);
32 sink (p);
33
34 p = cpy_a4 + 2;
35 p = memcpy (p, s, n - 2);
36 sink (p);
37 memcpy (p, s, n - 2);
38 sink (p);
39
40 p = cpy_a4 + 3;
41 p = memcpy (p, s, n - 3);
42 sink (p);
43 memcpy (p, s, n - 3);
44 sink (p);
45
46 p = cpy_a4 + 4;
47 p = memcpy (p, s, n - 4);
48 sink (p);
49 memcpy (p, s, n - 4);
50 sink (p);
51 }
52
53
54 void nowarn_memcpy_chain (const void *s)
55 {
56 extern char cpy_a8[8];
57
58 char *p = cpy_a8;
59
60 p = memcpy (p + 1, s, 7);
61 sink (p);
62
63 p = memcpy (p + 2 , s, 5);
64 sink (p);
65
66 p = memcpy (p + 3 , s, 2);
67 sink (p);
68
69 p = memcpy (p + 1 , s, 1);
70 sink (p);
71
72 p = memcpy (p - 7 , s, 8);
73 sink (p);
74
75 memcpy (p + 1, s, 7);
76 }
77
78
79 void warn_memcpy (const void *s)
80 {
81 extern char cpy_a5[5]; // { dg-message "destination object 'cpy_a5'" "note" }
82
83 unsigned n = sizeof cpy_a5;
84 void *p = cpy_a5;
85
86 p = memcpy (p, s, n);
87 sink (p);
88 memcpy (p, s, n + 1); // { dg-warning "writing 6 bytes into a region of size 5" }
89 sink (p);
90
91 p = cpy_a5;
92 p = memcpy (p, s, n);
93 sink (p);
94 memcpy (p, s, n + 1); // { dg-warning "writing 6 bytes into a region of size 5" }
95 sink (p);
96
97 p = cpy_a5 + 1;
98 p = memcpy (p, s, n - 1);
99 sink (p);
100 memcpy (p, s, n); // { dg-warning "writing 5 bytes into a region of size 4" }
101 sink (p);
102 }
103
104
105 void warn_memcpy_chain (const void *s)
106 {
107 extern char cpy_a8[8]; // { dg-message "destination object 'cpy_a8'" "note" }
108
109 char *p = cpy_a8;
110
111 p = memcpy (p, s, 9); // { dg-warning "writing 9 bytes into a region of size 8" }
112 sink (p);
113
114 p = memcpy (p + 2, s, 7); // { dg-warning "writing 7 bytes into a region of size 6" }
115 sink (p);
116
117 p = memcpy (p + 3, s, 5); // { dg-warning "writing 5 bytes into a region of size 3" }
118 sink (p);
119
120 p = memcpy (p + 3, s, 3); // { dg-warning "writing 3 bytes into a region of size 0" }
121 sink (p);
122 }
123
124
125 void nowarn_mempcpy (const void *s)
126 {
127 extern char a4[4];
128 unsigned n = sizeof a4;
129
130 char *p = mempcpy (a4, s, n);
131 sink (p);
132 mempcpy (p - 4, s, n);
133 sink (p);
134
135 p = mempcpy (a4 + 1, s, n - 1);
136 sink (p);
137 mempcpy (p - 4, s, n);
138 sink (p);
139
140 p = mempcpy (a4 + 2, s, n - 2);
141 sink (p);
142 mempcpy (p - 4, s, n);
143 sink (p);
144
145 p = mempcpy (a4 + 3, s, n - 3);
146 sink (p);
147 mempcpy (p - 4, s, n);
148 sink (p);
149
150 p = mempcpy (a4 + 4, s, n - 4);
151 sink (p);
152 mempcpy (p - 4, s, n);
153 sink (p);
154 }
155
156
157 void nowarn_mempcpy_chain (const void *s)
158 {
159 extern char pcpy_a8[8];
160
161 char *p = pcpy_a8;
162
163 p = mempcpy (p + 1, s, 7);
164 sink (p);
165
166 p = mempcpy (p - 7 , s, 7);
167 sink (p);
168
169 p = mempcpy (p - 5 , s, 5);
170 sink (p);
171
172 p = mempcpy (p - 3 , s, 3);
173 sink (p);
174
175 p = mempcpy (p - 2 , s, 2);
176 sink (p);
177
178 mempcpy (p - 1, s, 1);
179 sink (p);
180
181 mempcpy (p - 8, s, 8);
182 }
183
184
185 void warn_mempcpy (const void *s)
186 {
187 extern char pcpy_a5[5]; // { dg-message "destination object 'pcpy_a5'" "note" }
188
189 char *p = pcpy_a5;
190
191 p = mempcpy (p, s, 5);
192 sink (p);
193 mempcpy (p - 5, s, 6); // { dg-warning "writing 6 bytes into a region of size 5 " }
194 sink (p);
195
196 p = pcpy_a5;
197 p = mempcpy (p, s, 3);
198 sink (p);
199 mempcpy (p, s, 3); // { dg-warning "writing 3 bytes into a region of size 2 " }
200 sink (p);
201
202 p = pcpy_a5 + 1;
203 p = mempcpy (p, s, 3);
204 sink (p);
205 mempcpy (p - 1, s, 5); // { dg-warning "writing 5 bytes into a region of size 2 " }
206 sink (p);
207 }
208
209
210 void warn_mempcpy_chain_3 (const void *s)
211 {
212 char *p = malloc (5); // { dg-message "at offset \\\[3, 5] into destination object of size 5" "note" }
213 p = mempcpy (p, s, UR (1, 2));
214 p = mempcpy (p, s, UR (2, 3));
215 p = mempcpy (p, s, UR (3, 4)); // { dg-warning "writing between 3 and 4 bytes into a region of size 2 " }
216
217 sink (p);
218 }
219
220 void warn_mempcpy_offrng_chain_3 (const void *s)
221 {
222 char *p = malloc (11); // { dg-message "at offset \\\[9, 11] into destination object of size 11 " "note" }
223 size_t r1_2 = UR (1, 2);
224 size_t r2_3 = r1_2 + 1;
225 size_t r3_4 = r2_3 + 1;
226
227 p = mempcpy (p + r1_2, s, r1_2);
228 p = mempcpy (p + r2_3, s, r2_3);
229 p = mempcpy (p + r3_4, s, r3_4); // { dg-warning "writing between 3 and 4 bytes into a region of size 2 " }
230
231 sink (p);
232 }
233
234 void warn_mempcpy_chain_4 (const void *s)
235 {
236 char *p = malloc (9); // { dg-message "at offset \\\[6, 9] into destination object of size 9 " "note" }
237 p = mempcpy (p, s, UR (1, 2));
238 p = mempcpy (p, s, UR (2, 3));
239 p = mempcpy (p, s, UR (3, 4));
240 p = mempcpy (p, s, UR (4, 5)); // { dg-warning "writing between 4 and 5 bytes into a region of size 3 " }
241
242 sink (p);
243 }
244
245 void warn_mempcpy_chain_5 (const void *s)
246 {
247 char *p = malloc (14); // { dg-message "at offset \\\[10, 14] into destination object of size 14 " "note" }
248 p = mempcpy (p, s, UR (1, 2));
249 p = mempcpy (p, s, UR (2, 3));
250 p = mempcpy (p, s, UR (3, 4));
251 p = mempcpy (p, s, UR (4, 5));
252 p = mempcpy (p, s, UR (5, 6)); // { dg-warning "writing between 5 and 6 bytes into a region of size 4 " }
253
254 sink (p);
255 }