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

Dominique Martinet <npfhrotynz-ptnqh.myvf at noclue dot notk.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
         Resolution|FIXED                       |---
             Status|RESOLVED                    |REOPENED

--- Comment #4 from Dominique Martinet <npfhrotynz-ptnqh.myvf at noclue dot 
notk.org> ---
Thanks for the fix!
I've compiled gcc from master and can confirm this fixes the warning for the
example I provided... But unfortunately it doesn't fix it for my real
application, so my reproducer was simplified too much :/

(It fails on this file:
https://github.com/cea-hpc/coordinatool/blob/06c5e319e3c934256d51c2af3ba5f7551bac4bff/copytool/coordinatool.c
, but this project requires lustre development headers to compile so it's not a
good reproducer)


Here's a new attempt, this also gives a similar warning without a precise
location on gcc master:
-------
#include <getopt.h>
#include <stdlib.h>
#include <string.h>

char *xstrdup(const char *src) {
        char *val = strdup(src);
        if (!val)
                abort();
        return val;
}

struct test {
        char *one, *two;
};

int main(int argc, char *argv[]) {
        struct test *options = calloc(1, sizeof(*options));
        int rc;
        if (!options)
                abort();

        while ((rc = getopt(argc, argv, "a:b:")) != -1) {
                switch (rc) {
                case 'a':
                        free(options->one);
                        options->one = xstrdup(optarg);
                        break;
                case 'b':
                        free(options->two);
                        options->two = xstrdup(optarg);
                        break;
                }
        }
        free(options->one);
        free(options->two);
        free(options);
        return 0;
}
-------


----
In function ‘main’:
cc1: warning: leak of ‘<unknown>’ [CWE-401] [-Wanalyzer-malloc-leak]
  ‘main’: events 1-2
    |
    |/tmp/t4.c:16:5:
    |   16 | int main(int argc, char *argv[]) {
    |      |     ^~~~
    |      |     |
    |      |     (1) entry to ‘main’
    |......
    |   19 |         if (!options)
    |      |            ~
    |      |            |
    |      |            (2) following ‘false’ branch (when ‘options’ is
non-NULL)...
    |
  ‘main’: event 3
    |
    |cc1:
    | (3): ...to here
    |
  ‘main’: events 4-6
    |
    |   22 |         while ((rc = getopt(argc, argv, "a:b:")) != -1) {
    |      |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~
    |      |                                                  |
    |      |                                                  (4) following
‘true’ branch (when ‘rc != -1’)...
    |   23 |                 switch (rc) {
    |      |                 ~~~~~~                            
    |      |                 |
    |      |                 (5) ...to here
    |......
    |   30 |                         options->two = xstrdup(optarg);
    |      |                                        ~~~~~~~~~~~~~~~
    |      |                                        |
    |      |                                        (6) calling ‘xstrdup’ from
‘main’
    |
    +--> ‘xstrdup’: events 7-11
           |
           |    5 | char *xstrdup(const char *src) {
           |      |       ^~~~~~~
           |      |       |
           |      |       (7) entry to ‘xstrdup’
           |    6 |         char *val = strdup(src);
           |      |                     ~~~~~~~~~~~
           |      |                     |
           |      |                     (8) allocated here
           |    7 |         if (!val)
           |      |            ~
           |      |            |
           |      |            (9) assuming ‘val’ is non-NULL
           |      |            (10) following ‘false’ branch (when ‘val’ is
non-NULL)...
           |    8 |                 abort();
           |    9 |         return val;
           |      |                ~~~
           |      |                |
           |      |                (11) ...to here
           |
    <------+
    |
  ‘main’: event 12
    |
    |   30 |                         options->two = xstrdup(optarg);
    |      |                                        ^~~~~~~~~~~~~~~
    |      |                                        |
    |      |                                        (12) returning to ‘main’
from ‘xstrdup’
    |
  ‘main’: event 13
    |
    |cc1:
    | (13): ‘<unknown>’ leaks here; was allocated at (8)
    |
----

I'm not sure it's accurate enough for my usecase though: in my project the
"option" struct is declared on the stack and not dynamically allocated... and I
cannot reproduce with "struct test option = { 0 };" so I'm not sure where this
is different; I'll try a bit more and update this ticket if I find a better
reproducer.

(What do you prefer to move forward -- I've tried reopening the bug but you
really fixed something so should I open a new bz instead and keep this
resolved?)

Reply via email to