/* Example of a multilevel wrapper around malloc, with an unchecked write. */ /* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-path-format=inline-events -fanalyzer-checker=malloc -fdiagnostics-show-caret -fanalyzer-verbose-state-changes" } */ /* { dg-enable-nn-line-numbers "" } */ #include void *wrapped_malloc (size_t size) { return malloc (size); } typedef struct boxed_int { int i; } boxed_int; boxed_int * make_boxed_int (int i) { boxed_int *result = (boxed_int *)wrapped_malloc (sizeof (boxed_int)); result->i = i; /* { dg-warning "dereference of possibly-NULL 'result'" } */ return result; } /* "dereference of possibly-NULL 'result' [CWE-690]". */ /* { dg-begin-multiline-output "" } NN | result->i = i; | ~~~~~~~~~~^~~ 'make_boxed_int': events 1-2 | | NN | make_boxed_int (int i) | | ^~~~~~~~~~~~~~ | | | | | (1) entry to 'make_boxed_int' | NN | { | NN | boxed_int *result = (boxed_int *)wrapped_malloc (sizeof (boxed_int)); | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | | | | | (2) calling 'wrapped_malloc' from 'make_boxed_int' | +--> 'wrapped_malloc': events 3-4 | | NN | void *wrapped_malloc (size_t size) | | ^~~~~~~~~~~~~~ | | | | | (3) entry to 'wrapped_malloc' | NN | { | NN | return malloc (size); | | ~~~~~~~~~~~~~ | | | | | (4) this call could return NULL (state of '': 'start' -> 'unchecked', origin: NULL) | <------+ | 'make_boxed_int': events 5-6 | | NN | boxed_int *result = (boxed_int *)wrapped_malloc (sizeof (boxed_int)); | | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | | | | | (5) possible return of NULL to 'make_boxed_int' from 'wrapped_malloc' | NN | result->i = i; | | ~~~~~~~~~~~~~ | | | | | (6) 'result' could be NULL: unchecked value from (4) ('result' is in state 'unchecked') | { dg-end-multiline-output "" } */