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

            Bug ID: 104434
           Summary: Analyzer doesn't know about "pure" and "const"
                    functions
           Product: gcc
           Version: 12.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: ---

Consider:

extern int pure_p (int) __attribute__ ((pure));
extern void do_stuff (void);

void test (int a)
{
  void *p;
  if (pure_p (a))
    {
      p = __builtin_malloc (1024);
      if (!p)
        return;
    }
  do_stuff ();
  if (pure_p (a))
    __builtin_free (p);
}

Currently trunk -fanalyzer emits these warnings:

/tmp/foo.c: In function ‘test’:
/tmp/foo.c:14:6: warning: leak of ‘p’ [CWE-401] [-Wanalyzer-malloc-leak]
   14 |   if (pure_p (a))
      |      ^
  ‘test’: events 1-7
    |
    |    7 |   if (pure_p (a))
    |      |      ^
    |      |      |
    |      |      (1) following ‘true’ branch...
    |    8 |     {
    |    9 |       p = __builtin_malloc (1024);
    |      |           ~~~~~~~~~~~~~~~~~~~~~~~
    |      |           |
    |      |           (2) ...to here
    |      |           (3) allocated here
    |   10 |       if (!p)
    |      |          ~
    |      |          |
    |      |          (4) assuming ‘p’ is non-NULL
    |      |          (5) following ‘false’ branch (when ‘p’ is non-NULL)...
    |......
    |   13 |   do_stuff ();
    |      |   ~~~~~~~~~~~
    |      |   |
    |      |   (6) ...to here
    |   14 |   if (pure_p (a))
    |      |      ~
    |      |      |
    |      |      (7) following ‘false’ branch...
    |
  ‘test’: event 8
    |
    |cc1:
    | (8): ...to here
    |
  ‘test’: event 9
    |
    |   14 |   if (pure_p (a))
    |      |      ^
    |      |      |
    |      |      (9) ‘p’ leaks here; was allocated at (3)
    |
/tmp/foo.c:15:5: warning: use of uninitialized value ‘p’ [CWE-457]
[-Wanalyzer-use-of-uninitialized-value]
   15 |     __builtin_free (p);
      |     ^~~~~~~~~~~~~~~~~~
  ‘test’: events 1-6
    |
    |    6 |   void *p;
    |      |         ^
    |      |         |
    |      |         (1) region created on stack here
    |    7 |   if (pure_p (a))
    |      |      ~   
    |      |      |
    |      |      (2) following ‘false’ branch...
    |......
    |   13 |   do_stuff ();
    |      |   ~~~~~~~~~~~
    |      |   |
    |      |   (3) ...to here
    |   14 |   if (pure_p (a))
    |      |      ~   
    |      |      |
    |      |      (4) following ‘true’ branch...
    |   15 |     __builtin_free (p);
    |      |     ~~~~~~~~~~~~~~~~~~
    |      |     |
    |      |     (5) ...to here
    |      |     (6) use of uninitialized value ‘p’ here
    |

by considering the execution paths where
  pure_p (a)
is true then false (the false leak diagnostic), and false then true (the false
uninit diagnostic)

Presumably the analyzer should consider that the result of a pure/const
function doesn't change, and thus only considers the true/true and false/false
paths.

Reply via email to