-fanalyzer false positive on gcc 12.1 and gcc 12.2

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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>: In function 'avl_insert':
<source>:58:15: warning: leak of '<unknown>' [CWE-401]
[-Wanalyzer-malloc-leak]
   58 |         if (!(*n))
      |              ~^~~
  'avl_insert': events 1-8
    |
    |   38 |         if (bt->size == SIZE_MAX)
    |      |            ^
    |      |            |
    |      |            (1) following 'false' branch...
    |......
    |   41 |         struct Binary_Tree_Node **bn = &(bt->root);
    |      |                                   ~~
    |      |                                   |
    |      |                                   (2) ...to here
    |......
    |   44 |         while (*bn) {
    |      |                ~
    |      |                |
    |      |                (3) following 'true' branch...
    |   45 |                 const int res = bt->comp(key, (*bn)->key);
    |      |                                 ~~~~~~~~
    |      |                                   |
    |      |                                   (4) ...to here
    |   46 |                 if (!res)
    |      |                    ~
    |      |                    |
    |      |                    (5) following 'false' branch (when 'res !=
0')...
    |   47 |                         return ERR_ELEMENT_EXISTS;
    |   48 |                 parent = *bn;
    |      |                 ~~~~~~~~~~~~
    |      |                        |
    |      |                        (6) ...to here
    |......
    |   57 |         *n = malloc(sizeof(**n));
    |      |              ~~~~~~~~~~~~~~~~~~~
    |      |              |
    |      |              (7) allocated here
    |   58 |         if (!(*n))
    |      |              ~~~~
    |      |               |
    |      |               (8) '<unknown>' leaks here; was allocated at (7)



[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux