public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug analyzer/103526] New: -fanalyzer considers memcpy()ed and returned pointer to malloc()ed memory a memory leak
@ 2021-12-02  4:09 guilherme.janczak at yandex dot com
  2021-12-02 16:39 ` [Bug analyzer/103526] " dmalcolm at gcc dot gnu.org
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: guilherme.janczak at yandex dot com @ 2021-12-02  4:09 UTC (permalink / raw)
  To: gcc-bugs

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

            Bug ID: 103526
           Summary: -fanalyzer considers memcpy()ed and returned pointer
                    to malloc()ed memory a memory leak
           Product: gcc
           Version: 11.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: analyzer
          Assignee: dmalcolm at gcc dot gnu.org
          Reporter: guilherme.janczak at yandex dot com
  Target Milestone: ---

Created attachment 51915
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=51915&action=edit
The preprocessed file output by '$ egcc -v -save-temps -fanalyzer example.c'

I found this while trying -fanalyzer on my hangman game. The attached
preprocessed file comes from the "example.c" file as requested by the bug
writing guidelines.

It seems that my allocator function game_new() triggers a bug. It creates a
struct game_state in the stack with the identifier 'tmp', as well as a pointer
to the same kind of struct with the identifier 'rval'. It assigns the return
value of malloc() to a member of 'tmp', then it allocates storage for 'rval',
and then it memcpy()es 'tmp' into the storage 'rval' points to and returns
'rval'. 
GCC's static analyzer seems to think the pointer inside 'tmp' leaks at the end
of the function because it's not smart enough to realize it has been returned
through 'rval'.

Here's the file "example.c" which triggers this bug:
#include <stdlib.h>
#include <string.h>

struct game_state {
        const char *word; /* This is a pointer to static storage. */
        char       *word_state;
};

const char *const teststr = "test string";

static struct game_state *game_new(void);
static void game_free(struct game_state *);

int
main(void)
{
        struct game_state *game;
        if ((game = game_new()) == NULL)
                exit(1);
        game_free(game);
        exit(0);
}

static struct game_state *
game_new(void)
{
        struct game_state tmp = {0};
        struct game_state *rval = NULL;
        size_t wordlen;

        tmp.word = teststr;
        wordlen = strlen(tmp.word);
        if ((tmp.word_state = malloc(wordlen+1)) == NULL)
                goto err;
        if ((rval = malloc(sizeof(*rval))) == NULL)
                goto err;
        memcpy(rval, &tmp, sizeof(*rval));

        return (rval);
err:
        free(tmp.word_state);
        free(rval);
        return (NULL);
}

static void
game_free(struct game_state *game)
{
        if (game == NULL)
                return;
        free(game->word_state);
        free(game);
}



$ egcc -v -save-temps -fanalyzer example.c
Using built-in specs.
COLLECT_GCC=egcc
COLLECT_LTO_WRAPPER=/usr/local/libexec/gcc/x86_64-unknown-openbsd7.0/11.2.0/lto-wrapper
Target: x86_64-unknown-openbsd7.0
Configured with: /usr/obj/ports/gcc-11.2.0/gcc-11.2.0/configure
--with-stage1-ldflags=-L/usr/obj/ports/gcc-11.2.0/bootstrap/lib --verbose
--program-transform-name='s,^,e,' --disable-nls --with-system-zlib
--disable-libmudflap --disable-libgomp --disable-libssp --disable-tls
--with-gnu-ld --with-gnu-as --enable-threads=posix --enable-wchar_t
--with-gmp=/usr/local --enable-languages=c,c++,fortran,objc,ada,d
--disable-libstdcxx-pch --enable-default-ssp --enable-default-pie --without-isl
--enable-cpp --prefix=/usr/local --sysconfdir=/etc --mandir=/usr/local/man
--infodir=/usr/local/info --localstatedir=/var --disable-silent-rules
--disable-gtk-doc
Thread model: posix
Supported LTO compression algorithms: zlib
gcc version 11.2.0 (GCC) 
COLLECT_GCC_OPTIONS='-v' '-save-temps' '-fanalyzer' '-mtune=generic'
'-march=x86-64' '-dumpdir' 'a-'
 /usr/local/libexec/gcc/x86_64-unknown-openbsd7.0/11.2.0/cc1 -E -quiet -v
example.c -mtune=generic -march=x86-64 -fanalyzer -fpch-preprocess -o
a-example.i
ignoring nonexistent directory
"/usr/local/lib/gcc/x86_64-unknown-openbsd7.0/11.2.0/../../../../x86_64-unknown-openbsd7.0/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/local/lib/gcc/x86_64-unknown-openbsd7.0/11.2.0/include
 /usr/local/lib/gcc/x86_64-unknown-openbsd7.0/11.2.0/include-fixed
 /usr/include
End of search list.
COLLECT_GCC_OPTIONS='-v' '-save-temps' '-fanalyzer' '-mtune=generic'
'-march=x86-64' '-dumpdir' 'a-'
 /usr/local/libexec/gcc/x86_64-unknown-openbsd7.0/11.2.0/cc1 -fpreprocessed
a-example.i -quiet -dumpdir a- -dumpbase example.c -dumpbase-ext .c
-mtune=generic -march=x86-64 -version -fanalyzer -o a-example.s
GNU C17 (GCC) version 11.2.0 (x86_64-unknown-openbsd7.0)
        compiled by GNU C version 11.2.0, GMP version 6.2.1, MPFR version
4.1.0, MPC version 1.1.0, isl version none
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
GNU C17 (GCC) version 11.2.0 (x86_64-unknown-openbsd7.0)
        compiled by GNU C version 11.2.0, GMP version 6.2.1, MPFR version
4.1.0, MPC version 1.1.0, isl version none
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: b55fd2c5b9d1ebf92b67661bceac5878
example.c: In function 'game_new':
example.c:44:1: warning: leak of 'tmp.word_state' [CWE-401]
[-Wanalyzer-malloc-leak]
   44 | }
      | ^
  'game_new': events 1-3
    |
    |example.c:33:31:
    |   33 |         if ((tmp.word_state = malloc(wordlen+1)) == NULL)
    |      |            ~                  ^~~~~~~~~~~~~~~~~
    |      |            |                  |
    |      |            |                  (1) allocated here
    |      |            (2) assuming 'tmp.word_state' is non-NULL
    |      |            (3) following 'false' branch...
    |
  'game_new': events 4-5
    |
    |example.c:35:21:
    |   35 |         if ((rval = malloc(sizeof(*rval))) == NULL)
    |      |            ~        ^~~~~~~~~~~~~~~~~~~~~
    |      |            |        |
    |      |            |        (4) ...to here
    |      |            (5) following 'false' branch (when 'rval' is
non-NULL)...
    |
  'game_new': event 6
    |
    |example.c:37:9:
    |   37 |         memcpy(rval, &tmp, sizeof(*rval));
    |      |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    |      |         |
    |      |         (6) ...to here
    |
  'game_new': event 7
    |
    |example.c:44:1:
    |   44 | }
    |      | ^
    |      | |
    |      | (7) 'tmp.word_state' leaks here; was allocated at (1)
    |
COLLECT_GCC_OPTIONS='-v' '-save-temps' '-fanalyzer' '-mtune=generic'
'-march=x86-64' '-dumpdir' 'a-'
 as -v -o a-example.o a-example.s
GNU assembler version 2.17 (amd64-unknown-openbsd7.0) using BFD version 2.17
COMPILER_PATH=/usr/local/libexec/gcc/x86_64-unknown-openbsd7.0/11.2.0/:/usr/local/libexec/gcc/x86_64-unknown-openbsd7.0/11.2.0/:/usr/local/libexec/gcc/x86_64-unknown-openbsd7.0/:/usr/local/lib/gcc/x86_64-unknown-openbsd7.0/11.2.0/:/usr/local/lib/gcc/x86_64-unknown-openbsd7.0/
LIBRARY_PATH=/usr/local/lib/gcc/x86_64-unknown-openbsd7.0/11.2.0/:/usr/local/lib/gcc/x86_64-unknown-openbsd7.0/11.2.0/../../../:/usr/lib/
COLLECT_GCC_OPTIONS='-v' '-save-temps' '-fanalyzer' '-mtune=generic'
'-march=x86-64' '-dumpdir' 'a.'
 /usr/local/libexec/gcc/x86_64-unknown-openbsd7.0/11.2.0/collect2
--eh-frame-hdr -e __start -Bdynamic -dynamic-linker /usr/libexec/ld.so
-L/usr/lib /usr/lib/crt0.o /usr/lib/crtbegin.o
-L/usr/local/lib/gcc/x86_64-unknown-openbsd7.0/11.2.0
-L/usr/local/lib/gcc/x86_64-unknown-openbsd7.0/11.2.0/../../.. a-example.o
-lgcc -lc -lgcc /usr/lib/crtend.o
COLLECT_GCC_OPTIONS='-v' '-save-temps' '-fanalyzer' '-mtune=generic'
'-march=x86-64' '-dumpdir' 'a.'

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [Bug analyzer/103526] -fanalyzer considers memcpy()ed and returned pointer to malloc()ed memory a memory leak
  2021-12-02  4:09 [Bug analyzer/103526] New: -fanalyzer considers memcpy()ed and returned pointer to malloc()ed memory a memory leak guilherme.janczak at yandex dot com
@ 2021-12-02 16:39 ` dmalcolm at gcc dot gnu.org
  2021-12-02 19:05 ` cvs-commit at gcc dot gnu.org
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: dmalcolm at gcc dot gnu.org @ 2021-12-02 16:39 UTC (permalink / raw)
  To: gcc-bugs

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

David Malcolm <dmalcolm at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |ASSIGNED
   Last reconfirmed|                            |2021-12-02
     Ever confirmed|0                           |1

--- Comment #1 from David Malcolm <dmalcolm at gcc dot gnu.org> ---
Thanks for filing this bug.

It affects gcc 11.2: https://godbolt.org/z/focGvsesh
but is fixed in trunk for GCC 12 : https://godbolt.org/z/hc5f7vWPY

I've rewritten the pertinent parts of -fanalyzer's internals a fair amount for
GCC 12.

I'm working on adding the test case to our regression testsuite.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [Bug analyzer/103526] -fanalyzer considers memcpy()ed and returned pointer to malloc()ed memory a memory leak
  2021-12-02  4:09 [Bug analyzer/103526] New: -fanalyzer considers memcpy()ed and returned pointer to malloc()ed memory a memory leak guilherme.janczak at yandex dot com
  2021-12-02 16:39 ` [Bug analyzer/103526] " dmalcolm at gcc dot gnu.org
@ 2021-12-02 19:05 ` cvs-commit at gcc dot gnu.org
  2021-12-02 19:07 ` dmalcolm at gcc dot gnu.org
  2022-01-07  6:37 ` pinskia at gcc dot gnu.org
  3 siblings, 0 replies; 5+ messages in thread
From: cvs-commit at gcc dot gnu.org @ 2021-12-02 19:05 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #2 from CVS Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by David Malcolm <dmalcolm@gcc.gnu.org>:

https://gcc.gnu.org/g:38a0ee2649ef236ea2763bb9cfc42dc917c7d3fd

commit r12-5757-g38a0ee2649ef236ea2763bb9cfc42dc917c7d3fd
Author: David Malcolm <dmalcolm@redhat.com>
Date:   Thu Dec 2 11:48:04 2021 -0500

    analyzer: add regression test for leak false +ve [PR103526]

    gcc/testsuite/ChangeLog:
            PR analyzer/103526
            * gcc.dg/analyzer/pr103526.c: New test.

    Signed-off-by: David Malcolm <dmalcolm@redhat.com>

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [Bug analyzer/103526] -fanalyzer considers memcpy()ed and returned pointer to malloc()ed memory a memory leak
  2021-12-02  4:09 [Bug analyzer/103526] New: -fanalyzer considers memcpy()ed and returned pointer to malloc()ed memory a memory leak guilherme.janczak at yandex dot com
  2021-12-02 16:39 ` [Bug analyzer/103526] " dmalcolm at gcc dot gnu.org
  2021-12-02 19:05 ` cvs-commit at gcc dot gnu.org
@ 2021-12-02 19:07 ` dmalcolm at gcc dot gnu.org
  2022-01-07  6:37 ` pinskia at gcc dot gnu.org
  3 siblings, 0 replies; 5+ messages in thread
From: dmalcolm at gcc dot gnu.org @ 2021-12-02 19:07 UTC (permalink / raw)
  To: gcc-bugs

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

David Malcolm <dmalcolm at gcc dot gnu.org> changed:

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

--- Comment #3 from David Malcolm <dmalcolm at gcc dot gnu.org> ---
Regression test added to trunk by above commit; marking as resolved.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [Bug analyzer/103526] -fanalyzer considers memcpy()ed and returned pointer to malloc()ed memory a memory leak
  2021-12-02  4:09 [Bug analyzer/103526] New: -fanalyzer considers memcpy()ed and returned pointer to malloc()ed memory a memory leak guilherme.janczak at yandex dot com
                   ` (2 preceding siblings ...)
  2021-12-02 19:07 ` dmalcolm at gcc dot gnu.org
@ 2022-01-07  6:37 ` pinskia at gcc dot gnu.org
  3 siblings, 0 replies; 5+ messages in thread
From: pinskia at gcc dot gnu.org @ 2022-01-07  6:37 UTC (permalink / raw)
  To: gcc-bugs

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

Andrew Pinski <pinskia at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
   Target Milestone|---                         |12.0

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2022-01-07  6:37 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-12-02  4:09 [Bug analyzer/103526] New: -fanalyzer considers memcpy()ed and returned pointer to malloc()ed memory a memory leak guilherme.janczak at yandex dot com
2021-12-02 16:39 ` [Bug analyzer/103526] " dmalcolm at gcc dot gnu.org
2021-12-02 19:05 ` cvs-commit at gcc dot gnu.org
2021-12-02 19:07 ` dmalcolm at gcc dot gnu.org
2022-01-07  6:37 ` pinskia at gcc dot gnu.org

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).