1 /* Example of a multilevel wrapper around malloc, with an unchecked write. */
2
3 /* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-path-format=inline-events -fanalyzer-checker=malloc -fdiagnostics-show-caret -fanalyzer-verbose-state-changes" } */
4 /* { dg-enable-nn-line-numbers "" } */
5
6 #include <stdlib.h>
7
wrapped_malloc(size_t size)8 void *wrapped_malloc (size_t size)
9 {
10 return malloc (size);
11 }
12
13 typedef struct boxed_int
14 {
15 int i;
16 } boxed_int;
17
18 boxed_int *
make_boxed_int(int i)19 make_boxed_int (int i)
20 {
21 boxed_int *result = (boxed_int *)wrapped_malloc (sizeof (boxed_int));
22 result->i = i; /* { dg-warning "dereference of possibly-NULL 'result'" } */
23 return result;
24 }
25
26 /* "dereference of possibly-NULL 'result' [CWE-690]". */
27 /* { dg-begin-multiline-output "" }
28 NN | result->i = i;
29 | ~~~~~~~~~~^~~
30 'make_boxed_int': events 1-2
31 |
32 | NN | make_boxed_int (int i)
33 | | ^~~~~~~~~~~~~~
34 | | |
35 | | (1) entry to 'make_boxed_int'
36 | NN | {
37 | NN | boxed_int *result = (boxed_int *)wrapped_malloc (sizeof (boxed_int));
38 | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
39 | | |
40 | | (2) calling 'wrapped_malloc' from 'make_boxed_int'
41 |
42 +--> 'wrapped_malloc': events 3-4
43 |
44 | NN | void *wrapped_malloc (size_t size)
45 | | ^~~~~~~~~~~~~~
46 | | |
47 | | (3) entry to 'wrapped_malloc'
48 | NN | {
49 | NN | return malloc (size);
50 | | ~~~~~~~~~~~~~
51 | | |
52 | | (4) this call could return NULL (state of '<return-value>': 'start' -> 'unchecked', origin: NULL)
53 |
54 <------+
55 |
56 'make_boxed_int': events 5-6
57 |
58 | NN | boxed_int *result = (boxed_int *)wrapped_malloc (sizeof (boxed_int));
59 | | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
60 | | |
61 | | (5) possible return of NULL to 'make_boxed_int' from 'wrapped_malloc'
62 | NN | result->i = i;
63 | | ~~~~~~~~~~~~~
64 | | |
65 | | (6) 'result' could be NULL: unchecked value from (4) ('result' is in state 'unchecked')
66 |
67 { dg-end-multiline-output "" } */
68