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

            Bug ID: 109059
           Summary: -Wanalyzer-malloc-leak false +ve seen on haproxy's
                    cfgparse.c: cfg_register_postparser
           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: ---

Given:
----------------------------------------------------------------------------
/* Reduced from haproxy-2.7.1's cfgparse.c.  */

typedef __SIZE_TYPE__ size_t;

extern void*
calloc(size_t __nmemb, size_t __size)
  __attribute__((__nothrow__, __leaf__))
  __attribute__((__malloc__)) __attribute__((__alloc_size__(1, 2)));

struct list
{
  struct list* n;
  struct list* p;
};

struct cfg_postparser
{
  struct list list;
  char* name;
  int (*func)();
};

extern struct list postparsers;

int
cfg_register_postparser(char* name, int (*func)())
{
  struct cfg_postparser* cp;

  cp = calloc(1, sizeof(*cp));
  if (!cp) {
    /* [...snip...] */
    return 0;
  }
  cp->name = name;
  cp->func = func;

  ({
    (&cp->list)->p = (&postparsers)->p;
    (&cp->list)->p->n = (&postparsers)->p = (&cp->list);
    (&cp->list)->n = (&postparsers);
    (&cp->list);
  });

  return 1;
}
----------------------------------------------------------------------------

...we currently emit this false positive:

----------------------------------------------------------------------------
../../src/haproxy-cfgparse-leak.c: In function ‘cfg_register_postparser’:
../../src/haproxy-cfgparse-leak.c:45:10: warning: leak of ‘cp’ [CWE-401]
[-Wanalyzer-malloc-leak] [num_events: 5]
   45 |   return 1;
      |          ^
  ‘cfg_register_postparser’: events 1-5
    |
    |   30 |   cp = calloc(1, sizeof(*cp));
    |      |        ^~~~~~~~~~~~~~~~~~~~~~
    |      |        |
    |      |        (1) allocated here
    |   31 |   if (!cp) {
    |      |      ~  
    |      |      |
    |      |      (2) assuming ‘cp’ is non-NULL
    |      |      (3) following ‘false’ branch (when ‘cp’ is non-NULL)...
    |......
    |   35 |   cp->name = name;
    |      |   ~~~~~~~~~~~~~~~
    |      |            |
    |      |            (4) ...to here
    |......
    |   45 |   return 1;
    |      |          ~
    |      |          |
    |      |          (5) ‘cp’ leaks here; was allocated at (1)
    |
----------------------------------------------------------------------------

   Trunk:  https://godbolt.org/z/WG6W16r1d
GCC 12.2: https://godbolt.org/z/d9afTcKqx
GCC 11.3: https://godbolt.org/z/aoaM7Mcze
GCC 10.4: https://godbolt.org/z/jY65dTccE

Reply via email to