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.

Reply via email to