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