public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug analyzer] -Wanalyser-malloc-leak false positive on gcc 12.1/12.2
@ 2023-02-27 13:38 Martin Georgiev
  0 siblings, 0 replies; only message in thread
From: Martin Georgiev @ 2023-02-27 13:38 UTC (permalink / raw)
  To: gcc-bugs

[-- Attachment #1: Type: text/plain, Size: 4442 bytes --]

I send this to gcc-help but it would probably be more appropriate.
While compiling a source file with the -fanalyzer option I got a compiler
-Wanalyser-malloc-leak warning. I followed the diagnostic message but
didn't see the problem so I decided to go look at the assembly code.
Compiling the same source file with gcc 11 and gcc trunk generated
identical assembly code but I did not get the error message. Is this a gcc
12 bug or am I missing something?

You can recreate the behavior described above by switching between
different gcc versions on godbolt.org.


#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>

struct Binary_Tree_Node {
    struct Binary_Tree_Node *left;
    struct Binary_Tree_Node *right;
    struct Binary_Tree_Node *parent;
    void *key;
};

typedef struct{
    struct Binary_Tree_Node *root;
    int (*comp)(const void *, const void *);
    void (*key_destr)(void *);
    size_t size;
} Binary_Tree;

struct AVL_Node {
        struct Binary_Tree_Node node;
        int balance;
};

typedef struct {
        Binary_Tree tree;
} AVL_Tree;


enum cdsa_err {ERR_OK = 0, ERR_OUT_OF_MEM, ERR_ELEMENT_NOT_FOUND,
ERR_ELEMENT_EXISTS, ERR_TREE_IS_FULL};

__attribute__((nonnull(1), access(read_write, 1), access(read_only, 2)))
extern enum cdsa_err avl_insert(AVL_Tree * const t, void * const key);


extern enum cdsa_err avl_insert(AVL_Tree * const t, void * const key)
{
        Binary_Tree * const bt = (Binary_Tree * const)t;
        if (bt->size == SIZE_MAX)
                return ERR_TREE_IS_FULL;

        struct Binary_Tree_Node **bn = &(bt->root);
        struct Binary_Tree_Node *parent = NULL;

        // Removing this traversal loop which shouldn't have any effect
removes the diagnose.
        while (*bn) {
                const int res = bt->comp(key, (*bn)->key);
                if (!res)
                        return ERR_ELEMENT_EXISTS;
                parent = *bn;
                if (res < 0) {
                        bn = &(*bn)->left;
                        continue;
                }
                bn = &(*bn)->right;
        }

        struct AVL_Node **n = (struct AVL_Node **)bn;
        *n = malloc(sizeof(**n));
        if (!(*n))
                return ERR_OUT_OF_MEM;

        (*bn)->key = key;
        (*bn)->left = NULL;
        (*bn)->right = NULL;
        (*bn)->parent = parent;
        (*n)->balance = 0;

        //balance_insert(t, *n);
        ++(bt->size);

        return ERR_OK;
}



Here is the output:


<source>:60:9: warning: leak of '<unknown>' [CWE-401]
[-Wanalyzer-malloc-leak]
   60 |         (*bn)->right = NULL;
      |         ^
  'avl_insert': events 1-11
    |
    |   35 |         if (bt->size == SIZE_MAX)
    |      |            ^
    |      |            |
    |      |            (1) following 'false' branch...
    |......
    |   38 |         struct Binary_Tree_Node **bn = &(bt->root);
    |      |         ~~~~~~
    |      |         |
    |      |         (2) ...to here
    |......
    |   41 |         while (*bn) {
    |      |                ~
    |      |                |
    |      |                (3) following 'true' branch...
    |   42 |                 const int res = bt->comp(key, (*bn)->key);
    |      |                 ~~~~~
    |      |                 |
    |      |                 (4) ...to here
    |   43 |                 if (!res)
    |      |                    ~
    |      |                    |
    |      |                    (5) following 'false' branch (when 'res !=
0')...
    |   44 |                         return ERR_ELEMENT_EXISTS;
    |   45 |                 parent = *bn;
    |      |                 ~~~~~~
    |      |                 |
    |      |                 (6) ...to here
    |......
    |   54 |         *n = malloc(sizeof(**n));
    |      |              ~~~~~~~~~~~~~~~~~~~
    |      |              |
    |      |              (7) allocated here
    |   55 |         if (!(*n))
    |      |            ~
    |      |            |
    |      |            (8) assuming 'malloc(40)' is non-NULL
    |      |            (9) following 'false' branch...
    |......
    |   58 |         (*bn)->key = key;
    |      |         ~
    |      |         |
    |      |         (10) ...to here
    |   59 |         (*bn)->left = NULL;
    |   60 |         (*bn)->right = NULL;
    |      |         ~
    |      |         |
    |      |         (11) '<unknown>' leaks here; was allocated at (7)

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-02-27 13:39 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-02-27 13:38 [Bug analyzer] -Wanalyser-malloc-leak false positive on gcc 12.1/12.2 Martin Georgiev

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).