https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108455
Bug ID: 108455 Summary: -Wanalyzer-deref-before-check false positive seen in git pack-revindex.c Product: gcc Version: 13.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: --- Created attachment 54299 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=54299&action=edit Reduced reproducer I'm attaching a reduced reproducer https://godbolt.org/z/7oMrno8rd Complains about: ../../src/pack-revindex.c: In function ‘load_revindex_from_disk’: ../../src/pack-revindex.c:123:8: warning: check of ‘data’ for NULL after already dereferencing it [-Wanalyzer-deref-before-check] 123 | if (data) | ^ ‘load_revindex_from_disk’: events 1-11 | | 63 | int load_revindex_from_disk(char *revindex_name, uint32_t num_objects, | | ^~~~~~~~~~~~~~~~~~~~~~~ | | | | | (1) entry to ‘load_revindex_from_disk’ |...... | 73 | if (fd < 0) { | | ~ | | | | | (2) following ‘false’ branch (when ‘fd >= 0’)... |...... | 77 | if (fstat(fd, &st)) { | | ~~~~~~~~~~~~~~~ | | || | | |(3) ...to here | | (4) following ‘false’ branch... |...... | 82 | revindex_size = xsize_t(st.st_size); | | ~~~~~~~~~~~~~~~~~~~ | | | | | (5) ...to here | 83 | | 84 | if (revindex_size < ((12) + (2 * the_repository->hash_algo->rawsz))) { | | ~ | | | | | (6) following ‘false’ branch... |...... | 90 | if (revindex_size - ((12) + (2 * the_repository->hash_algo->rawsz)) != | | ~ ~~ | | | | | | (8) following ‘false’ branch... (7) ...to here |...... | 97 | data = xmmap(((void *)0), revindex_size, 0x1, 0x02, fd, 0); | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | | | | | (9) ...to here |...... | 100 | if (git_bswap32(hdr->signature) != 0x52494458) { | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ | | | | | (10) pointer ‘data’ is dereferenced here | 101 | ret = | 102 | (error(_("reverse-index file %s has unknown signature"), revindex_name), | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | | | | | (11) calling ‘_’ from ‘load_revindex_from_disk’ | +--> ‘_’: events 12-14 | | 37 | static inline __attribute__((format_arg(1))) const char *_(const char *msgid) { | | ^ | | | | | (12) entry to ‘_’ | 38 | if (!*msgid) | | ~ | | | | | (13) following ‘false’ branch... | 39 | return ""; | 40 | return gettext(msgid); | | ~~~~~~~~~~~~~~ | | | | | (14) ...to here | <------+ | ‘load_revindex_from_disk’: events 15-18 | | 102 | (error(_("reverse-index file %s has unknown signature"), revindex_name), | | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | | | | | (15) returning to ‘load_revindex_from_disk’ from ‘_’ |...... | 122 | if (ret) { | | ~ | | | | | (16) following ‘true’ branch (when ‘ret != 0’)... | 123 | if (data) | | ~ | | | | | (17) ...to here | | (18) pointer ‘data’ is checked for NULL here but it was already dereferenced at (10) | Yes it does check the pointer for NULL after dereferencing it, but this is in shared cleanup code. There are other paths to the check for NULL in which the pointer hasn't yet been dereferenced.