https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95758
Bug ID: 95758
Summary: -Wanalyzer-use-after-free false positive when
compiling glibc regex.c
Product: gcc
Version: 10.1.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: analyzer
Assignee: dmalcolm at gcc dot gnu.org
Reporter: eggert at cs dot ucla.edu
Target Milestone: ---
Created attachment 48755
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=48755&action=edit
compressed .i file illustrating the -Wanalyzer-use-after-free false positive
When using GCC 10.1.0 -fanalyzer to compile Glibc/Gnulib regex.c I found
several -fanalyzer false positives. Most seem to come from GCC bugs already
reported (Bug#93695, Bug#94458, Bug#94851) but one might be new. To reproduce
the problem on x86-64, uncompress the attached file t4b.i.gz and the compile
t4b.i with the command:
gcc -S -fanalyzer -Wno-analyzer-double-free -Wno-analyzer-malloc-leak
-Wno-analyzer-null-dereference t4b.i
This should be a clean compile, but the output is the following, which is a
false alarm:
t4b.i: In function 'free_charset':
t4b.i:11582:13: warning: use after 'free' of 'cset' [CWE-416]
[-Wanalyzer-use-after-free]
11582 | free (cset->mbchars);
| ~~~~^~~~~~~~~
'rpl_regfree': events 1-4
|
| 7610 | rpl_regfree (regex_t *preg)
| | ^~~~~~~~~~~
| | |
| | (1) entry to 'rpl_regfree'
|......
| 7613 | if (__builtin_expect ((dfa !=
| | ~
| | |
| | (2) following 'true' branch...
|......
| 7618 | free_dfa_content (dfa);
| | ~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (3) ...to here
| | (4) calling 'free_dfa_content' from 'rpl_regfree'
|
+--> 'free_dfa_content': events 5-10
|
| 7566 | free_dfa_content (re_dfa_t *dfa)
| | ^~~~~~~~~~~~~~~~
| | |
| | (5) entry to 'free_dfa_content'
|......
| 7569 | if (dfa->nodes)
| | ~
| | |
| | (6) following 'true' branch...
| 7570 | for (i = 0; i < dfa->nodes_len; ++i)
| | ~~~ ~~~~~
| | | |
| | | (7) ...to here
| | (8) following 'true' branch...
| 7571 | free_token (dfa->nodes + i);
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | | |
| | | (9) ...to here
| | (10) calling 'free_token' from 'free_dfa_content'
|
+--> 'free_token': events 11-15
|
|11648 | free_token (re_token_t *node)
| | ^~~~~~~~~~
| | |
| | (11) entry to 'free_token'
|11649 | {
|11650 | if (node->type == COMPLEX_BRACKET &&
node->duplicated == 0)
| |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | | |
|
| | | |
(13) ...to here
| | | (14) following
'true' branch...
| | (12) following 'true' branch...
|11651 | free_charset (node->opr.mbcset);
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (15) ...to here
|
<------+
|
'free_dfa_content': events 16-19
|
| 7570 | for (i = 0; i < dfa->nodes_len; ++i)
| | ~~~
| | |
| | (17) following 'true' branch...
| 7571 | free_token (dfa->nodes + i);
| | ^~~~~~~~~~~~~~~~~~~~~~~~~~~
| | | |
| | | (18) ...to here
| | (16) returning to 'free_dfa_content' from
'free_token'
| | (19) calling 'free_token' from 'free_dfa_content'
|
+--> 'free_token': events 20-24
|
|11648 | free_token (re_token_t *node)
| | ^~~~~~~~~~
| | |
| | (20) entry to 'free_token'
|11649 | {
|11650 | if (node->type == COMPLEX_BRACKET &&
node->duplicated == 0)
| |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | | |
|
| | | |
(22) ...to here
| | | (23) following
'true' branch...
| | (21) following 'true' branch...
|11651 | free_charset (node->opr.mbcset);
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (24) ...to here
|
<------+
|
'free_dfa_content': events 25-28
|
| 7570 | for (i = 0; i < dfa->nodes_len; ++i)
| | ~~~
| | |
| | (26) following 'true' branch...
| 7571 | free_token (dfa->nodes + i);
| | ^~~~~~~~~~~~~~~~~~~~~~~~~~~
| | | |
| | | (27) ...to here
| | (25) returning to 'free_dfa_content' from
'free_token'
| | (28) calling 'free_token' from 'free_dfa_content'
|
+--> 'free_token': events 29-35
|
|11648 | free_token (re_token_t *node)
| | ^~~~~~~~~~
| | |
| | (29) entry to 'free_token'
|11649 | {
|11650 | if (node->type == COMPLEX_BRACKET &&
node->duplicated == 0)
| |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | | |
|
| | | |
(31) ...to here
| | | (32) following
'true' branch...
| | (30) following 'true' branch...
|11651 | free_charset (node->opr.mbcset);
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (33) ...to here
| | (34) freed here
| | (35) calling 'free_charset' from 'free_token'
|
+--> 'free_charset': events 36-37
|
|11580 | free_charset (re_charset_t *cset)
| | ^~~~~~~~~~~~
| | |
| | (36) entry to 'free_charset'
|11581 | {
|11582 | free (cset->mbchars);
| | ~~~~~~~~~~~~~
| | |
| | (37) use after 'free' of 'cset';
freed at (34)
|