1 /* Adapted from malloc-1.c, but wrapping the pointers in a struct. */
2
3 /* { dg-require-effective-target alloca } */
4
5 #include <stdlib.h>
6
7 extern int foo (void);
8 extern int bar (void);
9 extern void could_free (void *);
10 extern void cant_free (const void *); /* since it's a const void *. */
11
12 typedef struct boxed_ptr { void *value; } boxed_ptr;
13
14 boxed_ptr
15 boxed_malloc (size_t sz)
16 {
17 boxed_ptr result;
18 result.value = malloc (sz);
19 return result;
20 }
21
22 boxed_ptr
23 boxed_free (boxed_ptr ptr)
24 {
25 free (ptr.value);
26 }
27
28 const boxed_ptr boxed_null = {NULL};
29
30 void test_1 (void)
31 {
32 boxed_ptr ptr;
33 ptr.value = malloc (1024);
34 free (ptr.value);
35 free (ptr.value); /* { dg-warning "double-'free' of 'ptr.value'" } */
36 }
37
38 void test_2 (boxed_ptr ptr)
39 {
40 free (ptr.value);
41 free (ptr.value); /* { dg-warning "double-'free' of 'ptr.value'" } */
42 }
43
44 boxed_ptr
45 test_3 (void)
46 {
47 boxed_ptr ptr;
48 ptr.value = malloc (sizeof (int));
49 *(int *)ptr.value = 42; /* { dg-warning "dereference of possibly-NULL 'ptr.value' \\\[CWE-690\\\]" } */
50 return ptr;
51 }
52
53 boxed_ptr
54 test_4 (void)
55 {
56 boxed_ptr ptr;
57 ptr.value = malloc (sizeof (int));
58 int *iptr = (int *)ptr.value;
59 if (iptr)
60 *iptr = 42;
61 else
62 *iptr = 43; /* { dg-warning "dereference of NULL 'iptr' \\\[CWE-476\\\]" } */
63 return ptr;
64 }
65
66 int test_5 (boxed_ptr ptr)
67 {
68 free (ptr.value);
69 return *(int *)ptr.value; /* { dg-warning "use after 'free' of 'ptr.value'" } */
70 }
71
72 void test_6 (void *ptr)
73 {
74 boxed_ptr q;
75 q.value = ptr;
76 free (ptr);
77 free (q.value); /* { dg-warning "double-'free' of 'ptr'" } */
78 }
79
80 void test_6a (boxed_ptr ptr)
81 {
82 boxed_ptr q;
83 q = ptr;
84 boxed_free (ptr);
85 free (q.value); /* { dg-warning "double-'free' of 'ptr.value'" } */
86 }
87
88 void test_7 (void)
89 {
90 boxed_ptr ptr = boxed_malloc(4096);
91 if (!ptr.value)
92 return;
93 __builtin_memset(ptr.value, 0, 4096);
94 boxed_free(ptr);
95 }
96
97 boxed_ptr test_8 (void)
98 {
99 boxed_ptr ptr = boxed_malloc(4096);
100 if (!ptr.value)
101 return boxed_null;
102 __builtin_memset(ptr.value, 0, 4096);
103 return ptr;
104 }
105
106 void test_9 (void)
107 {
108 boxed_ptr ptr = boxed_malloc (1024);
109
110 int i;
111 for (i = 0; i < 1024; i++)
112 free (ptr.value); /* { dg-warning "double-'free' of 'ptr.value'" } */
113 }
114
115 void test_10 (void)
116 {
117 boxed_ptr ptr = boxed_malloc (1024);
118
119 int i;
120 for (i = 0; i < 1024; i++)
121 foo ();
122
123 free (ptr.value);
124 free (ptr.value); /* { dg-warning "double-'free' of 'ptr.value'" } */
125 }
126
127 void test_11 (void)
128 {
129 boxed_ptr ptr = boxed_malloc (1024);
130
131 while (foo ())
132 bar ();
133
134 free (ptr.value);
135 free (ptr.value); /* { dg-warning "double-'free' of 'ptr.value'" } */
136 }
137
138 void test_12 (void)
139 {
140 boxed_ptr ptr = boxed_malloc (1024);
141
142 while (1)
143 {
144 free (ptr.value);
145 free (ptr.value); /* { dg-warning "double-'free' of 'ptr.value'" } */
146 }
147 }
148
149 void test_13 (void)
150 {
151 boxed_ptr p = boxed_malloc (1024);
152 boxed_ptr q = boxed_malloc (1024);
153
154 foo ();
155 if (!q.value)
156 {
157 boxed_free (q);
158 return; /* { dg-warning "leak of 'p.value'" } */
159 }
160 bar ();
161 boxed_free (q);
162 boxed_free (p);
163 }
164
165 void test_14 (void)
166 {
167 boxed_ptr p, q;
168 p = boxed_malloc (1024);
169 if (!p.value)
170 return;
171
172 q = boxed_malloc (1024);
173 if (!q.value)
174 {
175 boxed_free (p);
176 boxed_free (q);
177 /* oops: missing "return". */
178 }
179 bar ();
180 boxed_free (q); /* Although this looks like a double-'free' of q,
181 it's known to be NULL for the case where free is
182 called twice on it. */
183 free (p.value); /* { dg-warning "double-'free' of 'p.value'" } */
184 }
185
186 void test_15 (void)
187 {
188 boxed_ptr p, q;
189 p.value = NULL;
190 q.value = NULL;
191
192 p = boxed_malloc (1024);
193 if (!p.value)
194 goto fail;
195
196 foo ();
197
198 q = boxed_malloc (1024);
199 if (!q.value)
200 goto fail;
201
202 bar ();
203
204 fail:
205 boxed_free (q);
206 boxed_free (p);
207 }
208
209 void test_16 (void)
210 {
211 boxed_ptr p, q; /* { dg-message "region created on stack here" } */
212
213 p = boxed_malloc (1024);
214 if (!p.value)
215 goto fail;
216
217 foo ();
218
219 q = boxed_malloc (1024);
220 if (!q.value)
221 goto fail;
222
223 bar ();
224
225 fail:
226 boxed_free (q); /* { dg-warning "use of uninitialized value 'q'" } */
227 boxed_free (p);
228 }
229
230 void test_17 (void)
231 {
232 boxed_ptr ptr = boxed_malloc (1024);
233 } /* { dg-warning "leak of 'ptr.value'" } */
234
235 void test_18 (void)
236 {
237 boxed_ptr ptr = boxed_malloc (64);
238 ptr = boxed_null; /* { dg-warning "leak of 'ptr.value'" } */
239 }
240
241 void test_18a (void)
242 {
243 boxed_ptr ptr = boxed_malloc (64);
244 ptr.value = NULL; /* { dg-warning "leak of 'ptr.value'" } */
245 }
246
247 void test_19 (void)
248 {
249 boxed_ptr ptr = boxed_malloc (64);
250 free (ptr.value);
251 ptr.value = NULL;
252 free (ptr.value);
253 }
254
255 boxed_ptr global_ptr_20;
256
257 void test_20 (void)
258 {
259 global_ptr_20 = boxed_malloc (1024);
260 }
261
262 int *test_21 (int i)
263 {
264 boxed_ptr ptr = boxed_malloc (sizeof (int));
265 if (!ptr.value)
266 abort ();
267 *(int *)ptr.value = i;
268 return ptr.value;
269 }
270
271 boxed_ptr test_21a (int i)
272 {
273 boxed_ptr ptr = boxed_malloc (sizeof (int));
274 if (!ptr.value)
275 abort ();
276 *(int *)ptr.value = i;
277 return ptr;
278 }
279
280 void test_22 (void)
281 {
282 boxed_ptr ptr = boxed_malloc (1024);
283
284 int i;
285 for (i = 5; i < 10; i++)
286 foo ();
287
288 free (ptr.value);
289 free (ptr.value); /* { dg-warning "double-'free' of 'ptr.value'" } */
290 }
291
292 int test_24 (void)
293 {
294 boxed_ptr ptr;
295 ptr.value = __builtin_alloca (sizeof (int)); /* { dg-message "region created on stack here" } */
296 free (ptr.value); /* { dg-warning "'free' of 'ptr.value' which points to memory on the stack \\\[CWE-590\\\]" } */
297 }
298
299 int test_25 (void)
300 {
301 char tmp[100]; /* { dg-message "region created on stack here" } */
302 boxed_ptr p;
303 p.value = tmp;
304 free (p.value); /* { dg-warning "'free' of '&tmp' which points to memory on the stack \\\[CWE-590\\\]" } */
305 }
306
307 char global_buffer[100]; /* { dg-message "region created here" } */
308
309 int test_26 (void)
310 {
311 boxed_ptr p;
312 p.value = global_buffer;
313 free (p.value); /* { dg-warning "'free' of '&global_buffer' which points to memory not on the heap \\\[CWE-590\\\]" } */
314 }
315
316 struct coord {
317 float x;
318 float y;
319 };
320
321 boxed_ptr test_27 (void)
322 {
323 boxed_ptr p = boxed_malloc (sizeof (struct coord));
324 ((struct coord *)p.value)->x = 0.f; /* { dg-warning "dereference of possibly-NULL 'p.value' \\\[CWE-690\\\]" } */
325
326 /* Only the first such usage should be reported: */
327 ((struct coord *)p.value)->y = 0.f;
328
329 return p;
330 }
331
332 struct link
333 {
334 boxed_ptr m_ptr;
335 };
336
337 boxed_ptr test_29 (void)
338 {
339 boxed_ptr res = boxed_malloc (sizeof (struct link));
340 if (!res.value)
341 return boxed_null;
342 ((struct link *)res.value)->m_ptr = boxed_malloc (sizeof (struct link));
343 return res;
344 }
345
346 void test_31 (void)
347 {
348 struct link tmp;
349 boxed_ptr ptr = boxed_malloc (sizeof (struct link));
350 tmp.m_ptr = ptr;
351 } /* { dg-warning "leak" } */
352
353 void test_32 (void)
354 {
355 boxed_ptr ptr = boxed_malloc (1024);
356 could_free (ptr.value);
357 } /* { dg-bogus "leak" } */
358
359 void test_33 (void)
360 {
361 boxed_ptr ptr = boxed_malloc (1024);
362 cant_free (ptr.value);
363 } /* { dg-warning "leak of 'ptr.value'" } */
364
365 void test_34 (void)
366 {
367 float *q;
368 boxed_ptr p = boxed_malloc (sizeof (struct coord));
369 if (!p.value)
370 return;
371 ((struct coord *)p.value)->x = 0.0f;
372 q = &((struct coord *)p.value)->x;
373 boxed_free (p);
374 *q = 1.0f; /* { dg-warning "use after 'free' of 'q'" } */
375 };
376
377 int test_35 (void)
378 {
379 boxed_ptr ptr = boxed_malloc(4096);
380 if (!ptr.value)
381 return -1;
382 __builtin_memset(ptr.value, 0, 4096);
383 boxed_free(ptr);
384 return 0;
385 }
386
387 void test_36 (void)
388 {
389 boxed_ptr ptr = boxed_malloc(4096);
390 if (!ptr.value)
391 return;
392 __builtin_memset(ptr.value, 0, 4096);
393 boxed_free(ptr);
394 }
395
396 boxed_ptr test_37a (void)
397 {
398 boxed_ptr ptr = boxed_malloc(4096);
399 __builtin_memset(ptr.value, 0, 4096); /* { dg-warning "use of possibly-NULL 'ptr.value' where non-null expected \\\[CWE-690\\\]" } */
400 return ptr;
401 }
402
403 int test_37b (void)
404 {
405 boxed_ptr p = boxed_malloc(4096);
406 boxed_ptr q = boxed_malloc(4096);
407 if (p.value) {
408 __builtin_memset(p.value, 0, 4096); /* Not a bug: checked */
409 } else {
410 __builtin_memset(q.value, 0, 4096); /* { dg-warning "use of possibly-NULL 'q.value' where non-null expected \\\[CWE-690\\\]" } */
411 }
412 boxed_free(p);
413 boxed_free(q);
414 return 0;
415 }
416
417 extern void might_use_ptr (void *ptr);
418
419 void test_38(int i)
420 {
421 boxed_ptr p;
422
423 p = boxed_malloc(1024);
424 if (p.value) {
425 boxed_free(p);
426 might_use_ptr(p.value); /* { dg-warning "use after 'free' of 'p.value'" "" { xfail *-*-* } } */
427 // TODO: xfail
428 }
429 }
430
431 boxed_ptr
432 test_39 (int i)
433 {
434 boxed_ptr p = boxed_malloc(sizeof(int*));
435 *(int *)p.value = i; /* { dg-warning "dereference of possibly-NULL 'p.value' \\\[CWE-690\\\]" } */
436 return p;
437 }
438
439 boxed_ptr
440 test_41 (int flag)
441 {
442 boxed_ptr buffer;
443
444 if (flag) {
445 buffer = boxed_malloc(4096);
446 } else {
447 buffer = boxed_null;
448 }
449
450 ((char *)buffer.value)[0] = 'a'; /* { dg-warning "dereference of possibly-NULL 'buffer.value' \\\[CWE-690\\\]" "possibly-NULL" } */
451 /* { dg-warning "dereference of NULL" "NULL" { target *-*-* } .-1 } */
452
453 return buffer;
454 }
455
456 extern void might_take_ownership (boxed_ptr ptr);
457
458 void test_45 (void)
459 {
460 boxed_ptr p = boxed_malloc (1024);
461 might_take_ownership (p);
462 }
463
464 /* Free of function, and of label within function. */
465
466 void test_50a (void)
467 {
468 }
469
470 void test_50b (void)
471 {
472 boxed_ptr ptr;
473 ptr.value = test_50a;
474 free (ptr.value); /* { dg-warning "'free' of '&test_50a' which points to memory not on the heap \\\[CWE-590\\\]" } */
475 }
476
477 void test_50c (void)
478 {
479 my_label:
480 boxed_ptr ptr;
481 ptr.value = &&my_label;
482 free (ptr.value); /* { dg-warning "'free' of '&my_label' which points to memory not on the heap \\\[CWE-590\\\]" } */
483 }
484
485 /* { dg-prune-output "\\\[-Wfree-nonheap-object" } */