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

--- Comment #1 from David Malcolm <dmalcolm at gcc dot gnu.org> ---
The C case in comment #0 doesn't look like what I think you meant to write, and
the analyzer (correctly IMHO) complains about a leak:

<source>: In function 'init':
<source>:22:61: warning: leak of 'p' [CWE-401] [-Wanalyzer-malloc-leak]
   22 | void init (struct A *p, int n) { p = alloc (n * sizeof *p); }
      |                                                             ^
  'init': events 1-2
    |
    |   22 | void init (struct A *p, int n) { p = alloc (n * sizeof *p); }
    |      |                                      ^~~~~~~~~~~~~~~~~~~~~  ~
    |      |                                      |                      |
    |      |                                      |                      (2)
'p' leaks here; was allocated at (1)
    |      |                                      (1) allocated here
    |
Compiler returned: 0


If I fix it up thus:

struct A { int *p; };

void dealloc (void*);
__attribute__ ((malloc (dealloc))) void* alloc (int);

void init (struct A *a, int n) { a->p = alloc (n * sizeof *a->p); }
void fini (struct A *a)
{
  __builtin_free (a->p);  // missing -Wmismatched-dealloc
}

void test (void)
{
    struct A a;
    init (&a, 5);
    fini (&a);
}
/* to provide an example of usage, otherwise the analyzer doesn't "know" about
the connection between init and fini */

then -fanalyzer warns about it:

<source>: In function 'fini':
<source>:27:3: warning: 'a.p' should have been deallocated with 'dealloc' but
was deallocated with 'free' [CWE-762] [-Wanalyzer-mismatching-deallocation]
   27 |   __builtin_free (a->p);  // missing -Wmismatched-dealloc
      |   ^~~~~~~~~~~~~~~~~~~~~
  'test': events 1-2
    |
    |   30 | void test (void)
    |      |      ^~~~
    |      |      |
    |      |      (1) entry to 'test'
    |......
    |   33 |     init (&a, 5);
    |      |     ~~~~~~~~~~~~
    |      |     |
    |      |     (2) calling 'init' from 'test'
    |
    +--> 'init': events 3-4
           |
           |   24 | void init (struct A *a, int n) { a->p = alloc (n * sizeof
*a->p); }
           |      |      ^~~~                              
~~~~~~~~~~~~~~~~~~~~~~~~
           |      |      |                                  |
           |      |      |                                  (4) allocated here
(expects deallocation with 'dealloc')
           |      |      (3) entry to 'init'
           |
    <------+
    |
  'test': events 5-6
    |
    |   33 |     init (&a, 5);
    |      |     ^~~~~~~~~~~~
    |      |     |
    |      |     (5) returning to 'test' from 'init'
    |   34 |     fini (&a);
    |      |     ~~~~~~~~~
    |      |     |
    |      |     (6) calling 'fini' from 'test'
    |
    +--> 'fini': events 7-8
           |
           |   25 | void fini (struct A *a)
           |      |      ^~~~
           |      |      |
           |      |      (7) entry to 'fini'
           |   26 | {
           |   27 |   __builtin_free (a->p);  // missing -Wmismatched-dealloc
           |      |   ~~~~~~~~~~~~~~~~~~~~~
           |      |   |
           |      |   (8) deallocated with 'free' here; allocation at (4)
expects deallocation with 'dealloc'
           |
Compiler returned: 0

Reply via email to