https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98918
Bug ID: 98918 Summary: Analyzer false positives due to sm-state involving UNKNOWN pointers Product: gcc Version: 11.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: analyzer Assignee: dmalcolm at gcc dot gnu.org Reporter: dmalcolm at gcc dot gnu.org Target Milestone: --- Reported to me via email: > gcc -fanalyzer for the sample code below gives false positive results. > If I remove field ref from struct marker, no problem is reported. test.c ====== #include <stdlib.h> struct marker { struct marker *next; void *ref; }; struct data { struct marker *marker; }; void data_free(struct data d) { struct marker *nm, *m; m = d.marker; while (m) { nm = m->next; free(m->ref); free(m); m = nm; } } $ gcc test.c -fanalyzer -c test.c: In function ‘data_free’: test.c:17:20: warning: use after ‘free’ of ‘m’ [CWE-416] [-Wanalyzer-use-after-free] 17 | nm = m->next; | ~~~^~~~~~~~~ ‘data_free’: events 1-18 | | 16 | while (m) { | | ^ | | | | | (1) following ‘true’ branch (when ‘m’ is non-NULL)... | | (3) following ‘true’ branch (when ‘m’ is non-NULL)... | | (5) following ‘true’ branch (when ‘m’ is non-NULL)... | | (7) following ‘true’ branch (when ‘m’ is non-NULL)... | | (10) following ‘true’ branch (when ‘m’ is non-NULL)... | | (12) following ‘true’ branch (when ‘m’ is non-NULL)... | | (14) following ‘true’ branch (when ‘m’ is non-NULL)... | | (16) following ‘true’ branch (when ‘m’ is non-NULL)... | 17 | nm = m->next; | | ~~~~~~~~~~~~ | | | | | (2) ...to here | | (4) ...to here | | (6) ...to here | | (8) ...to here | | (11) ...to here | | (13) ...to here | | (15) ...to here | | (17) ...to here | | (18) use after ‘free’ of ‘m’; freed at (9) | 18 | free(m->ref); | 19 | free(m); | | ~~~~~~~ | | | | | (9) freed here | test.c:18:17: warning: double-‘free’ of ‘*m.ref’ [CWE-415] [-Wanalyzer-double-free] 18 | free(m->ref); | ^~~~~~~~~~~~ ‘data_free’: events 1-16 | | 16 | while (m) { | | ^ | | | | | (1) following ‘true’ branch (when ‘m’ is non-NULL)... | | (3) following ‘true’ branch (when ‘m’ is non-NULL)... | | (5) following ‘true’ branch (when ‘m’ is non-NULL)... | | (8) following ‘true’ branch (when ‘m’ is non-NULL)... | | (10) following ‘true’ branch (when ‘m’ is non-NULL)... | | (12) following ‘true’ branch (when ‘m’ is non-NULL)... | | (14) following ‘true’ branch (when ‘m’ is non-NULL)... | 17 | nm = m->next; | | ~~~~~~~~~~~~ | | | | | (2) ...to here | | (4) ...to here | | (6) ...to here | | (9) ...to here | | (11) ...to here | | (13) ...to here | | (15) ...to here | 18 | free(m->ref); | | ~~~~~~~~~~~~ | | | | | (7) first ‘free’ here | | (16) second ‘free’ here; first ‘free’ was at (7) |