https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100417

            Bug ID: 100417
           Summary: False positive -Wmaybe-uninitalized with malloc.
           Product: gcc
           Version: 11.1.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: jkb at sanger dot ac.uk
  Target Milestone: ---

With gcc 11.1.0 and -Wall, if we malloc a block of memory and pass this pointer
to a function taking a const char * argument then we get a "may be used
uninitialized" warning.  That is perhaps a reasonable assessment given the data
cannot be modified by the function and nor was it initialised by the malloc.

However in the scenario of passing in both a char * and const char * pointer to
the same block of memory, the warning is still reported.  This is a false
positive.

An example usage would be a function which writes to a pointer, but also has a
second pointer to the end of the buffer to act as bounds checking.  This is a
valid idiom as an alternative to maintaining a remaining-length argument.

The simple code below demonstrates this issue:

#include <stdio.h>
#include <stdlib.h>

void fill(char *start, const char *end); // works if const is removed

char *func(void) {
    char *dat;
    //if (!(dat = calloc(1, 10))) // also works
    if (!(dat = malloc(10)))
        return NULL;

    fill(dat, dat+10);
    return dat;
}


$ gcc -Wa
ll -c _.c
_.c: In function 'func':
_.c:12:5: warning: '<unknown>' may be used uninitialized
[-Wmaybe-uninitialized]
   12 |     fill(dat, dat+10);
      |     ^~~~~~~~~~~~~~~~~
_.c:4:6: note: by argument 2 of type 'const char *' to 'fill' declared here
    4 | void fill(char *start, const char *end);
      |      ^~~~


Using "char *end" in fill or calloc instead of malloc removes this warning.
The more complete example where this test case was culled from is here:

https://github.com/samtools/htslib/pull/1280/checks?check_run_id=2499621360
from this code
https://github.com/samtools/htslib/blob/636c4207e1f4a6a1f310aecfa9b1e6bd13e921f6/cram/cram_codecs.c#L1901-L1938

My belief is that as dat and dat+10 are both pointers to the same object (NB
dat+9 gives the same warning so it's not a 1-past-the-end thing) then
validation should be done against the weakest form of pointer (char * in this
case) for all pointers to that object.

I can confirm that -Wextra -fno-strict-aliasing -fwrapv does not change this
behaviour.  

Gcc was built from source, using ../configure
--prefix=/software/badger/opt/gcc/11.1.0 --disable-multilib --disable-bootstrap
and contrib/download_prerequisites.

Regards,
James

Reply via email to