public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug analyzer/109614] New: -Wanalyzer-use-after-free gets confused about a free function in Coreutils
@ 2023-04-25 0:17 eggert at cs dot ucla.edu
0 siblings, 0 replies; only message in thread
From: eggert at cs dot ucla.edu @ 2023-04-25 0:17 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109614
Bug ID: 109614
Summary: -Wanalyzer-use-after-free gets confused about a free
function in Coreutils
Product: gcc
Version: 13.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 54915
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=54915&action=edit
bug reproducer
This is (GCC) 13.0.1 20230401 (Red Hat 13.0.1-0) on x86-64. Compile the
attached file (derived from GNU coreutils csplit) with:
gzip -d a.i.gz
gcc -fanalyzer -S a.i
The first warning is a false positive. As near as I can make out, -fanalyzer
got confused and is treating free_buffer as if it calls itself or was called
twice, which is obviously wrong (the diagnostic is confusing at any rate). The
full set of diagnostics is shown below.
a.i: In function ‘free_buffer’:
a.i:4491:21: warning: use after ‘free_buffer’ of ‘buf’ [CWE-416]
[-Wanalyzer-use-after-free]
4491 | for (struct line *l = buf->line_start; l;)
| ^
‘main’: events 1-6
|
| 5509 | main (int argc, char **argv)
| | ^~~~
| | |
| | (1) entry to ‘main’
|......
| 5588 | if (argc - optind < 2)
| | ~
| | |
| | (2) following ‘false’ branch...
|......
| 5598 | idx_t prefix_len = strlen (prefix);
| | ~~~~~~~~~~~~~~~
| | |
| | (3) ...to here
|......
| 5616 | if (__builtin_add_overflow (prefix_len,
max_digit_string_len + 1, &filename_size))
| | ~
| | |
| | (4) following ‘false’ branch...
| 5617 | xalloc_die ();
| 5618 | filename_space = ximalloc (filename_size);
| | ~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (5) ...to here
| 5619 | set_input_file (argv[optind++]);
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (6) calling ‘set_input_file’ from ‘main’
|
+--> ‘set_input_file’: events 7-11
|
| 4708 | set_input_file (char const *name)
| | ^~~~~~~~~~~~~~
| | |
| | (7) entry to ‘set_input_file’
| 4709 | {
| 4710 | if (! (strcmp (name, "-") == 0) && fd_reopen (
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | | | |
| | | | (9) ...to here
| | | (10) following
‘false’ branch...
| | (8) following ‘true’ branch (when the strings
are non-equal)...
| 4711 | 0
| | ~
| 4712 |
, name,
| |
~~~~~~~
| 4713 |
00
| |
~~
| 4714 |
, 0) < 0)
| |
~~~~~~~~
|......
| 4731 | }
| | ~
| | |
| | (11) ...to here
|
<------+
|
‘main’: events 12-21
|
| 5619 | set_input_file (argv[optind++]);
| | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (12) returning to ‘main’ from ‘set_input_file’
|......
| 5651 | for (i = 0; i < nsigs; i++)
| | ~~~~~~~~~
| | |
| | (13) following ‘true’ branch (when ‘i <=
10’)...
| | (15) following ‘true’ branch (when ‘i <=
10’)...
| 5652 | {
| 5653 | sigaction (sig[i],
| | ~~~~~~
| | |
| | (14) ...to here
| | (16) ...to here
|......
| 5668 | for (i = 0; i < nsigs; i++)
| | ~~~~~~~~~
| | |
| | (17) following ‘true’ branch (when ‘i <=
10’)...
| | (19) following ‘true’ branch (when ‘i <=
10’)...
| 5669 | if (sigismember (&caught_signals, sig[i]))
| | ~~~~~~
| | |
| | (18) ...to here
| | (20) ...to here
|......
| 5674 | split_file ();
| | ~~~~~~~~~~~~~
| | |
| | (21) calling ‘split_file’ from ‘main’
|
+--> ‘split_file’: events 22-29
|
| 4953 | split_file (void)
| | ^~~~~~~~~~
| | |
| | (22) entry to ‘split_file’
| 4954 | {
| 4955 | for (idx_t i = 0; i < control_used; i++)
| | ~~~~~~~~~~~~~~~~
| | |
| | (23) following ‘true’
branch...
|......
| 4958 | if (controls[i].regexpr)
| | ~ ~
| | | |
| | | (24) ...to here
| | (25) following ‘true’ branch...
| 4959 | {
| 4960 | for (j = 0; (controls[i].repeat_forever
| | ~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (26) ...to here
| 4961 | || j <= controls[i].repeat);
j++)
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (27) following ‘true’
branch...
| 4962 | process_regexp (&controls[i], j);
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (28) ...to here
| | (29) calling ‘process_regexp’ from
‘split_file’
|
+--> ‘process_regexp’: events 30-33
|
| 4845 | process_regexp (struct control *p, intmax_t
repetition)
| | ^~~~~~~~~~~~~~
| | |
| | (30) entry to ‘process_regexp’
|......
| 4853 | if (!ignore)
| | ~
| | |
| | (31) following ‘true’ branch...
| 4854 | create_output_file ();
| | ~~~~~~~~~~~~~~~~~~~~~
| | |
| | (32) ...to here
| | (33) calling ‘create_output_file’ from
‘process_regexp’
|
+--> ‘create_output_file’: events 34-38
|
| 4986 | create_output_file (void)
| | ^~~~~~~~~~~~~~~~~~
| | |
| | (34) entry to ‘create_output_file’
|......
| 4993 | if (nfiles == 0x7fffffff
| | ~
| | |
| | (35) following ‘false’ branch
(when ‘nfiles != 2147483647’)...
|......
| 5006 | sigprocmask (
| | ~~~~~~~~~~~~~
| | |
| | (36) ...to here
| 5007 | 0
| | ~
| 5008 | ,
&caught_signals, &oldset);
| |
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|......
| 5023 | if (! fopen_ok)
| | ~
| | |
| | (37) following ‘false’ branch...
|......
| 5028 | bytes_written = 0;
| | ~~~~~~~~~~~~~~~~~
| | |
| | (38) ...to here
|
<------+
|
‘process_regexp’: events 39-42
|
| 4854 | create_output_file ();
| | ^~~~~~~~~~~~~~~~~~~~~
| | |
| | (39) returning to ‘process_regexp’ from
‘create_output_file’
| 4855 | if (p->offset >= 0)
| | ~
| | |
| | (40) following ‘true’ branch...
|......
| 4861 | line = find_line (++current_line);
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (41) ...to here
| | (42) calling ‘find_line’
from ‘process_regexp’
|
+--> ‘find_line’: events 43-46
|
| 4654 | find_line (intmax_t linenum)
| | ^~~~~~~~~
| | |
| | (43) entry to ‘find_line’
|......
| 4657 | if (head ==
| | ~
| | |
| | (44) following ‘true’ branch...
| 4658 | ((void *)0)
| 4659 | && !load_buffer ())
| | ~~~~~~~~~~~~~~
| | |
| | (45) ...to here
| | (46) calling
‘load_buffer’ from ‘find_line’
|
+--> ‘load_buffer’: events 47-50
|
| 4542 | load_buffer (void)
| | ^~~~~~~~~~~
| | |
| | (47) entry to ‘load_buffer’
| 4543 | {
| 4544 | if (have_read_eof)
| | ~
| | |
| | (48) following ‘false’
branch...
|......
| 4549 | (((
| | ~~~
| 4550 | 8191
| | ~~~~
| 4551 | )>(
| | ~~~
| 4552 |
hold_count + 1
| |
~~~~~~~~~~~~~~
| 4553 | ))?(
| | ~~~~
| 4554 | 8191
| | ~~~~
| 4555 | ):(
| | ~~~
| | |
| | (49)
...to here
| 4556 |
hold_count + 1
| |
~~~~~~~~~~~~~~
| 4557 | ))
| | ~~
|......
| 4563 | struct buffer_record *b
= get_new_buffer (bytes_wanted);
| |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
|
| |
(50) calling ‘get_new_buffer’ from ‘load_buffer’
|
+--> ‘get_new_buffer’: events 51-52
|
| 4502 | get_new_buffer (idx_t
min_size)
| | ^~~~~~~~~~~~~~
| | |
| | (51) entry to
‘get_new_buffer’
| 4503 | {
| 4504 | struct buffer_record
*new_buffer = xmalloc (sizeof *new_buffer);
| |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
|
| |
(52) state of ‘&HEAP_ALLOCATED_REGION(1452)’: ‘start’ -> ‘nonnull’
(NULL origin)
|
<------+
|
‘load_buffer’: events 53-56
|
| 4563 | struct buffer_record *b
= get_new_buffer (bytes_wanted);
| |
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
|
| |
(53) returning to ‘load_buffer’ from ‘get_new_buffer’
|......
| 4567 | if (hold_count)
| | ~
| | |
| | (54) following
‘false’ branch...
|......
| 4574 | b->bytes_used +=
read_input (p, bytes_avail - 1);
| |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (55)
...to here
| | (56)
calling ‘read_input’ from ‘load_buffer’
|
+--> ‘read_input’: events 57-59
|
| 4391 | read_input (char *dest,
idx_t max_n_bytes)
| | ^~~~~~~~~~
| | |
| | (57) entry to
‘read_input’
|......
| 4394 | if (max_n_bytes == 0)
| | ~
| | |
| | (58) following
‘true’ branch (when ‘max_n_bytes == 0’)...
| 4395 | return 0;
| | ~
| | |
| | (59) ...to
here
|
<------+
|
‘load_buffer’: events 60-61
|
| 4574 | b->bytes_used +=
read_input (p, bytes_avail - 1);
| |
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (60)
returning to ‘load_buffer’ from ‘read_input’
| 4575 | if (record_line_starts
(b) != 0)
| |
~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (61) calling
‘record_line_starts’ from ‘load_buffer’
|
+--> ‘record_line_starts’: events 62-64
|
| 4449 | record_line_starts
(struct buffer_record *b)
| | ^~~~~~~~~~~~~~~~~~
| | |
| | (62) entry to
‘record_line_starts’
|......
| 4454 | if (b->bytes_used ==
0)
| | ~
| | |
| | (63) following
‘true’ branch...
| 4455 | return 0;
| | ~
| | |
| | (64) ...to
here
|
<------+
|
‘load_buffer’: events 65-69
|
| 4575 | if (record_line_starts
(b) != 0)
| |
~^~~~~~~~~~~~~~~~~~~~~~
| | ||
| | |(65) returning to
‘load_buffer’ from ‘record_line_starts’
| | (66) following
‘false’ branch...
|......
| 4582 | free_buffer (b);
| | ~~~~~~~~~~~~~~~
| | |
| | (67) ...to here
| | (68) deallocated here
| | (69) calling
‘free_buffer’ from ‘load_buffer’
|
+--> ‘free_buffer’: events 70-71
|
| 4489 | free_buffer (struct
buffer_record *buf)
| | ^~~~~~~~~~~
| | |
| | (70) entry to
‘free_buffer’
| 4490 | {
| 4491 | for (struct line *l =
buf->line_start; l;)
| | ~
| | |
| |
(71) use after ‘free_buffer’ of ‘buf’; deallocated at (68)
|
a.i: In function ‘get_new_buffer’:
a.i:4519:10: warning: leak of ‘b’ [CWE-401] [-Wanalyzer-malloc-leak]
4519 | return new_buffer;
| ^~~~~~~~~~
‘main’: events 1-6
|
| 5509 | main (int argc, char **argv)
| | ^~~~
| | |
| | (1) entry to ‘main’
|......
| 5588 | if (argc - optind < 2)
| | ~
| | |
| | (2) following ‘false’ branch...
|......
| 5598 | idx_t prefix_len = strlen (prefix);
| | ~~~~~~~~~~~~~~~
| | |
| | (3) ...to here
|......
| 5616 | if (__builtin_add_overflow (prefix_len,
max_digit_string_len + 1, &filename_size))
| | ~
| | |
| | (4) following ‘false’ branch...
| 5617 | xalloc_die ();
| 5618 | filename_space = ximalloc (filename_size);
| | ~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (5) ...to here
| 5619 | set_input_file (argv[optind++]);
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (6) calling ‘set_input_file’ from ‘main’
|
+--> ‘set_input_file’: events 7-11
|
| 4708 | set_input_file (char const *name)
| | ^~~~~~~~~~~~~~
| | |
| | (7) entry to ‘set_input_file’
| 4709 | {
| 4710 | if (! (strcmp (name, "-") == 0) && fd_reopen (
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | | | |
| | | | (9) ...to here
| | | (10) following
‘false’ branch...
| | (8) following ‘true’ branch (when the strings
are non-equal)...
| 4711 | 0
| | ~
| 4712 |
, name,
| |
~~~~~~~
| 4713 |
00
| |
~~
| 4714 |
, 0) < 0)
| |
~~~~~~~~
|......
| 4731 | }
| | ~
| | |
| | (11) ...to here
|
<------+
|
‘main’: events 12-21
|
| 5619 | set_input_file (argv[optind++]);
| | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (12) returning to ‘main’ from ‘set_input_file’
|......
| 5651 | for (i = 0; i < nsigs; i++)
| | ~~~~~~~~~
| | |
| | (13) following ‘true’ branch (when ‘i <=
10’)...
| | (15) following ‘true’ branch (when ‘i <=
10’)...
| 5652 | {
| 5653 | sigaction (sig[i],
| | ~~~~~~
| | |
| | (14) ...to here
| | (16) ...to here
|......
| 5668 | for (i = 0; i < nsigs; i++)
| | ~~~~~~~~~
| | |
| | (17) following ‘true’ branch (when ‘i <=
10’)...
| | (19) following ‘true’ branch (when ‘i <=
10’)...
| 5669 | if (sigismember (&caught_signals, sig[i]))
| | ~~~~~~
| | |
| | (18) ...to here
| | (20) ...to here
|......
| 5674 | split_file ();
| | ~~~~~~~~~~~~~
| | |
| | (21) calling ‘split_file’ from ‘main’
|
+--> ‘split_file’: events 22-29
|
| 4953 | split_file (void)
| | ^~~~~~~~~~
| | |
| | (22) entry to ‘split_file’
| 4954 | {
| 4955 | for (idx_t i = 0; i < control_used; i++)
| | ~~~~~~~~~~~~~~~~
| | |
| | (23) following ‘true’
branch...
|......
| 4958 | if (controls[i].regexpr)
| | ~ ~
| | | |
| | | (24) ...to here
| | (25) following ‘true’ branch...
| 4959 | {
| 4960 | for (j = 0; (controls[i].repeat_forever
| | ~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (26) ...to here
| 4961 | || j <= controls[i].repeat);
j++)
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (27) following ‘true’
branch...
| 4962 | process_regexp (&controls[i], j);
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (28) ...to here
| | (29) calling ‘process_regexp’ from
‘split_file’
|
+--> ‘process_regexp’: events 30-33
|
| 4845 | process_regexp (struct control *p, intmax_t
repetition)
| | ^~~~~~~~~~~~~~
| | |
| | (30) entry to ‘process_regexp’
|......
| 4853 | if (!ignore)
| | ~
| | |
| | (31) following ‘true’ branch...
| 4854 | create_output_file ();
| | ~~~~~~~~~~~~~~~~~~~~~
| | |
| | (32) ...to here
| | (33) calling ‘create_output_file’ from
‘process_regexp’
|
+--> ‘create_output_file’: events 34-38
|
| 4986 | create_output_file (void)
| | ^~~~~~~~~~~~~~~~~~
| | |
| | (34) entry to ‘create_output_file’
|......
| 4993 | if (nfiles == 0x7fffffff
| | ~
| | |
| | (35) following ‘false’ branch
(when ‘nfiles != 2147483647’)...
|......
| 5006 | sigprocmask (
| | ~~~~~~~~~~~~~
| | |
| | (36) ...to here
| 5007 | 0
| | ~
| 5008 | ,
&caught_signals, &oldset);
| |
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|......
| 5023 | if (! fopen_ok)
| | ~
| | |
| | (37) following ‘false’ branch...
|......
| 5028 | bytes_written = 0;
| | ~~~~~~~~~~~~~~~~~
| | |
| | (38) ...to here
|
<------+
|
‘process_regexp’: events 39-42
|
| 4854 | create_output_file ();
| | ^~~~~~~~~~~~~~~~~~~~~
| | |
| | (39) returning to ‘process_regexp’ from
‘create_output_file’
| 4855 | if (p->offset >= 0)
| | ~
| | |
| | (40) following ‘true’ branch...
|......
| 4861 | line = find_line (++current_line);
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (41) ...to here
| | (42) calling ‘find_line’
from ‘process_regexp’
|
+--> ‘find_line’: events 43-46
|
| 4654 | find_line (intmax_t linenum)
| | ^~~~~~~~~
| | |
| | (43) entry to ‘find_line’
|......
| 4657 | if (head ==
| | ~
| | |
| | (44) following ‘true’ branch...
| 4658 | ((void *)0)
| 4659 | && !load_buffer ())
| | ~~~~~~~~~~~~~~
| | |
| | (45) ...to here
| | (46) calling
‘load_buffer’ from ‘find_line’
|
+--> ‘load_buffer’: events 47-51
|
| 4542 | load_buffer (void)
| | ^~~~~~~~~~~
| | |
| | (47) entry to ‘load_buffer’
| 4543 | {
| 4544 | if (have_read_eof)
| | ~
| | |
| | (48) following ‘false’
branch...
|......
| 4549 | (((
| | ~~~
| 4550 | 8191
| | ~~~~
| 4551 | )>(
| | ~~~
| 4552 |
hold_count + 1
| |
~~~~~~~~~~~~~~
| 4553 | ))?(
| | ~~~~
| 4554 | 8191
| | ~~~~
| 4555 | ):(
| | ~~~
| | |
| | (49)
...to here
| 4556 |
hold_count + 1
| |
~~~~~~~~~~~~~~
| 4557 | ))
| | ~~
|......
| 4563 | struct buffer_record *b
= get_new_buffer (bytes_wanted);
| |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
|
| |
(50) allocated here
| |
(51) calling ‘get_new_buffer’ from ‘load_buffer’
|
+--> ‘get_new_buffer’: events 52-53
|
| 4502 | get_new_buffer (idx_t
min_size)
| | ^~~~~~~~~~~~~~
| | |
| | (52) entry to
‘get_new_buffer’
|......
| 4519 | return new_buffer;
| | ~~~~~~~~~~
| | |
| | (53) ‘b’ leaks
here; was allocated at (50)
|
a.i: In function ‘load_buffer’:
a.i:4582:7: warning: ‘b’ should have been deallocated with ‘free’ but
was deallocated with ‘free_buffer’ [CWE-762]
[-Wanalyzer-mismatching-deallocation]
4582 | free_buffer (b);
| ^~~~~~~~~~~~~~~
‘main’: events 1-6
|
| 5509 | main (int argc, char **argv)
| | ^~~~
| | |
| | (1) entry to ‘main’
|......
| 5588 | if (argc - optind < 2)
| | ~
| | |
| | (2) following ‘false’ branch...
|......
| 5598 | idx_t prefix_len = strlen (prefix);
| | ~~~~~~~~~~~~~~~
| | |
| | (3) ...to here
|......
| 5616 | if (__builtin_add_overflow (prefix_len,
max_digit_string_len + 1, &filename_size))
| | ~
| | |
| | (4) following ‘false’ branch...
| 5617 | xalloc_die ();
| 5618 | filename_space = ximalloc (filename_size);
| | ~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (5) ...to here
| 5619 | set_input_file (argv[optind++]);
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (6) calling ‘set_input_file’ from ‘main’
|
+--> ‘set_input_file’: events 7-11
|
| 4708 | set_input_file (char const *name)
| | ^~~~~~~~~~~~~~
| | |
| | (7) entry to ‘set_input_file’
| 4709 | {
| 4710 | if (! (strcmp (name, "-") == 0) && fd_reopen (
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | | | |
| | | | (9) ...to here
| | | (10) following
‘false’ branch...
| | (8) following ‘true’ branch (when the strings
are non-equal)...
| 4711 | 0
| | ~
| 4712 |
, name,
| |
~~~~~~~
| 4713 |
00
| |
~~
| 4714 |
, 0) < 0)
| |
~~~~~~~~
|......
| 4731 | }
| | ~
| | |
| | (11) ...to here
|
<------+
|
‘main’: events 12-21
|
| 5619 | set_input_file (argv[optind++]);
| | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (12) returning to ‘main’ from ‘set_input_file’
|......
| 5651 | for (i = 0; i < nsigs; i++)
| | ~~~~~~~~~
| | |
| | (13) following ‘true’ branch (when ‘i <=
10’)...
| | (15) following ‘true’ branch (when ‘i <=
10’)...
| 5652 | {
| 5653 | sigaction (sig[i],
| | ~~~~~~
| | |
| | (14) ...to here
| | (16) ...to here
|......
| 5668 | for (i = 0; i < nsigs; i++)
| | ~~~~~~~~~
| | |
| | (17) following ‘true’ branch (when ‘i <=
10’)...
| | (19) following ‘true’ branch (when ‘i <=
10’)...
| 5669 | if (sigismember (&caught_signals, sig[i]))
| | ~~~~~~
| | |
| | (18) ...to here
| | (20) ...to here
|......
| 5674 | split_file ();
| | ~~~~~~~~~~~~~
| | |
| | (21) calling ‘split_file’ from ‘main’
|
+--> ‘split_file’: events 22-29
|
| 4953 | split_file (void)
| | ^~~~~~~~~~
| | |
| | (22) entry to ‘split_file’
| 4954 | {
| 4955 | for (idx_t i = 0; i < control_used; i++)
| | ~~~~~~~~~~~~~~~~
| | |
| | (23) following ‘true’
branch...
|......
| 4958 | if (controls[i].regexpr)
| | ~ ~
| | | |
| | | (24) ...to here
| | (25) following ‘true’ branch...
| 4959 | {
| 4960 | for (j = 0; (controls[i].repeat_forever
| | ~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (26) ...to here
| 4961 | || j <= controls[i].repeat);
j++)
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (27) following ‘true’
branch...
| 4962 | process_regexp (&controls[i], j);
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (28) ...to here
| | (29) calling ‘process_regexp’ from
‘split_file’
|
+--> ‘process_regexp’: events 30-33
|
| 4845 | process_regexp (struct control *p, intmax_t
repetition)
| | ^~~~~~~~~~~~~~
| | |
| | (30) entry to ‘process_regexp’
|......
| 4853 | if (!ignore)
| | ~
| | |
| | (31) following ‘true’ branch...
| 4854 | create_output_file ();
| | ~~~~~~~~~~~~~~~~~~~~~
| | |
| | (32) ...to here
| | (33) calling ‘create_output_file’ from
‘process_regexp’
|
+--> ‘create_output_file’: events 34-38
|
| 4986 | create_output_file (void)
| | ^~~~~~~~~~~~~~~~~~
| | |
| | (34) entry to ‘create_output_file’
|......
| 4993 | if (nfiles == 0x7fffffff
| | ~
| | |
| | (35) following ‘false’ branch
(when ‘nfiles != 2147483647’)...
|......
| 5006 | sigprocmask (
| | ~~~~~~~~~~~~~
| | |
| | (36) ...to here
| 5007 | 0
| | ~
| 5008 | ,
&caught_signals, &oldset);
| |
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|......
| 5023 | if (! fopen_ok)
| | ~
| | |
| | (37) following ‘false’ branch...
|......
| 5028 | bytes_written = 0;
| | ~~~~~~~~~~~~~~~~~
| | |
| | (38) ...to here
|
<------+
|
‘process_regexp’: events 39-42
|
| 4854 | create_output_file ();
| | ^~~~~~~~~~~~~~~~~~~~~
| | |
| | (39) returning to ‘process_regexp’ from
‘create_output_file’
| 4855 | if (p->offset >= 0)
| | ~
| | |
| | (40) following ‘true’ branch...
|......
| 4861 | line = find_line (++current_line);
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (41) ...to here
| | (42) calling ‘find_line’
from ‘process_regexp’
|
+--> ‘find_line’: events 43-46
|
| 4654 | find_line (intmax_t linenum)
| | ^~~~~~~~~
| | |
| | (43) entry to ‘find_line’
|......
| 4657 | if (head ==
| | ~
| | |
| | (44) following ‘true’ branch...
| 4658 | ((void *)0)
| 4659 | && !load_buffer ())
| | ~~~~~~~~~~~~~~
| | |
| | (45) ...to here
| | (46) calling
‘load_buffer’ from ‘find_line’
|
+--> ‘load_buffer’: events 47-50
|
| 4542 | load_buffer (void)
| | ^~~~~~~~~~~
| | |
| | (47) entry to ‘load_buffer’
| 4543 | {
| 4544 | if (have_read_eof)
| | ~
| | |
| | (48) following ‘false’
branch...
|......
| 4549 | (((
| | ~~~
| 4550 | 8191
| | ~~~~
| 4551 | )>(
| | ~~~
| 4552 |
hold_count + 1
| |
~~~~~~~~~~~~~~
| 4553 | ))?(
| | ~~~~
| 4554 | 8191
| | ~~~~
| 4555 | ):(
| | ~~~
| | |
| | (49)
...to here
| 4556 |
hold_count + 1
| |
~~~~~~~~~~~~~~
| 4557 | ))
| | ~~
|......
| 4563 | struct buffer_record *b
= get_new_buffer (bytes_wanted);
| |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
|
| |
(50) calling ‘get_new_buffer’ from ‘load_buffer’
|
+--> ‘get_new_buffer’: events 51-52
|
| 4502 | get_new_buffer (idx_t
min_size)
| | ^~~~~~~~~~~~~~
| | |
| | (51) entry to
‘get_new_buffer’
| 4503 | {
| 4504 | struct buffer_record
*new_buffer = xmalloc (sizeof *new_buffer);
| |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
|
| |
(52) state of ‘&HEAP_ALLOCATED_REGION(1452)’: ‘start’ -> ‘nonnull’
(NULL origin)
|
<------+
|
‘load_buffer’: events 53-56
|
| 4563 | struct buffer_record *b
= get_new_buffer (bytes_wanted);
| |
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
|
| |
(53) returning to ‘load_buffer’ from ‘get_new_buffer’
|......
| 4567 | if (hold_count)
| | ~
| | |
| | (54) following
‘false’ branch...
|......
| 4574 | b->bytes_used +=
read_input (p, bytes_avail - 1);
| |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (55)
...to here
| | (56)
calling ‘read_input’ from ‘load_buffer’
|
+--> ‘read_input’: events 57-59
|
| 4391 | read_input (char *dest,
idx_t max_n_bytes)
| | ^~~~~~~~~~
| | |
| | (57) entry to
‘read_input’
|......
| 4394 | if (max_n_bytes == 0)
| | ~
| | |
| | (58) following
‘true’ branch (when ‘max_n_bytes == 0’)...
| 4395 | return 0;
| | ~
| | |
| | (59) ...to
here
|
<------+
|
‘load_buffer’: events 60-61
|
| 4574 | b->bytes_used +=
read_input (p, bytes_avail - 1);
| |
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (60)
returning to ‘load_buffer’ from ‘read_input’
| 4575 | if (record_line_starts
(b) != 0)
| |
~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (61) calling
‘record_line_starts’ from ‘load_buffer’
|
+--> ‘record_line_starts’: events 62-64
|
| 4449 | record_line_starts
(struct buffer_record *b)
| | ^~~~~~~~~~~~~~~~~~
| | |
| | (62) entry to
‘record_line_starts’
|......
| 4454 | if (b->bytes_used ==
0)
| | ~
| | |
| | (63) following
‘true’ branch...
| 4455 | return 0;
| | ~
| | |
| | (64) ...to
here
|
<------+
|
‘load_buffer’: events 65-68
|
| 4575 | if (record_line_starts
(b) != 0)
| |
~^~~~~~~~~~~~~~~~~~~~~~
| | ||
| | |(65) returning to
‘load_buffer’ from ‘record_line_starts’
| | (66) following
‘false’ branch...
|......
| 4582 | free_buffer (b);
| | ~~~~~~~~~~~~~~~
| | |
| | (67) ...to here
| | (68) deallocated with
‘free_buffer’ here
|
a.i:4582:7: warning: leak of ‘<unknown>’ [CWE-401]
[-Wanalyzer-malloc-leak]
4582 | free_buffer (b);
| ^~~~~~~~~~~~~~~
‘main’: events 1-6
|
| 5509 | main (int argc, char **argv)
| | ^~~~
| | |
| | (1) entry to ‘main’
|......
| 5588 | if (argc - optind < 2)
| | ~
| | |
| | (2) following ‘false’ branch...
|......
| 5598 | idx_t prefix_len = strlen (prefix);
| | ~~~~~~~~~~~~~~~
| | |
| | (3) ...to here
|......
| 5616 | if (__builtin_add_overflow (prefix_len,
max_digit_string_len + 1, &filename_size))
| | ~
| | |
| | (4) following ‘false’ branch...
| 5617 | xalloc_die ();
| 5618 | filename_space = ximalloc (filename_size);
| | ~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (5) ...to here
| 5619 | set_input_file (argv[optind++]);
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (6) calling ‘set_input_file’ from ‘main’
|
+--> ‘set_input_file’: events 7-11
|
| 4708 | set_input_file (char const *name)
| | ^~~~~~~~~~~~~~
| | |
| | (7) entry to ‘set_input_file’
| 4709 | {
| 4710 | if (! (strcmp (name, "-") == 0) && fd_reopen (
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | | | |
| | | | (9) ...to here
| | | (10) following
‘false’ branch...
| | (8) following ‘true’ branch (when the strings
are non-equal)...
| 4711 | 0
| | ~
| 4712 |
, name,
| |
~~~~~~~
| 4713 |
00
| |
~~
| 4714 |
, 0) < 0)
| |
~~~~~~~~
|......
| 4731 | }
| | ~
| | |
| | (11) ...to here
|
<------+
|
‘main’: events 12-21
|
| 5619 | set_input_file (argv[optind++]);
| | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (12) returning to ‘main’ from ‘set_input_file’
|......
| 5651 | for (i = 0; i < nsigs; i++)
| | ~~~~~~~~~
| | |
| | (13) following ‘true’ branch (when ‘i <=
10’)...
| | (15) following ‘true’ branch (when ‘i <=
10’)...
| 5652 | {
| 5653 | sigaction (sig[i],
| | ~~~~~~
| | |
| | (14) ...to here
| | (16) ...to here
|......
| 5668 | for (i = 0; i < nsigs; i++)
| | ~~~~~~~~~
| | |
| | (17) following ‘true’ branch (when ‘i <=
10’)...
| | (19) following ‘true’ branch (when ‘i <=
10’)...
| 5669 | if (sigismember (&caught_signals, sig[i]))
| | ~~~~~~
| | |
| | (18) ...to here
| | (20) ...to here
|......
| 5674 | split_file ();
| | ~~~~~~~~~~~~~
| | |
| | (21) calling ‘split_file’ from ‘main’
|
+--> ‘split_file’: events 22-29
|
| 4953 | split_file (void)
| | ^~~~~~~~~~
| | |
| | (22) entry to ‘split_file’
| 4954 | {
| 4955 | for (idx_t i = 0; i < control_used; i++)
| | ~~~~~~~~~~~~~~~~
| | |
| | (23) following ‘true’
branch...
|......
| 4958 | if (controls[i].regexpr)
| | ~ ~
| | | |
| | | (24) ...to here
| | (25) following ‘true’ branch...
| 4959 | {
| 4960 | for (j = 0; (controls[i].repeat_forever
| | ~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (26) ...to here
| 4961 | || j <= controls[i].repeat);
j++)
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (27) following ‘true’
branch...
| 4962 | process_regexp (&controls[i], j);
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (28) ...to here
| | (29) calling ‘process_regexp’ from
‘split_file’
|
+--> ‘process_regexp’: events 30-33
|
| 4845 | process_regexp (struct control *p, intmax_t
repetition)
| | ^~~~~~~~~~~~~~
| | |
| | (30) entry to ‘process_regexp’
|......
| 4853 | if (!ignore)
| | ~
| | |
| | (31) following ‘true’ branch...
| 4854 | create_output_file ();
| | ~~~~~~~~~~~~~~~~~~~~~
| | |
| | (32) ...to here
| | (33) calling ‘create_output_file’ from
‘process_regexp’
|
+--> ‘create_output_file’: events 34-38
|
| 4986 | create_output_file (void)
| | ^~~~~~~~~~~~~~~~~~
| | |
| | (34) entry to ‘create_output_file’
|......
| 4993 | if (nfiles == 0x7fffffff
| | ~
| | |
| | (35) following ‘false’ branch
(when ‘nfiles != 2147483647’)...
|......
| 5006 | sigprocmask (
| | ~~~~~~~~~~~~~
| | |
| | (36) ...to here
| 5007 | 0
| | ~
| 5008 | ,
&caught_signals, &oldset);
| |
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|......
| 5023 | if (! fopen_ok)
| | ~
| | |
| | (37) following ‘false’ branch...
|......
| 5028 | bytes_written = 0;
| | ~~~~~~~~~~~~~~~~~
| | |
| | (38) ...to here
|
<------+
|
‘process_regexp’: events 39-42
|
| 4854 | create_output_file ();
| | ^~~~~~~~~~~~~~~~~~~~~
| | |
| | (39) returning to ‘process_regexp’ from
‘create_output_file’
| 4855 | if (p->offset >= 0)
| | ~
| | |
| | (40) following ‘true’ branch...
|......
| 4861 | line = find_line (++current_line);
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (41) ...to here
| | (42) calling ‘find_line’
from ‘process_regexp’
|
+--> ‘find_line’: events 43-46
|
| 4654 | find_line (intmax_t linenum)
| | ^~~~~~~~~
| | |
| | (43) entry to ‘find_line’
|......
| 4657 | if (head ==
| | ~
| | |
| | (44) following ‘true’ branch...
| 4658 | ((void *)0)
| 4659 | && !load_buffer ())
| | ~~~~~~~~~~~~~~
| | |
| | (45) ...to here
| | (46) calling
‘load_buffer’ from ‘find_line’
|
+--> ‘load_buffer’: events 47-52
|
| 4542 | load_buffer (void)
| | ^~~~~~~~~~~
| | |
| | (47) entry to ‘load_buffer’
| 4543 | {
| 4544 | if (have_read_eof)
| | ~
| | |
| | (48) following ‘false’
branch...
|......
| 4549 | (((
| | ~~~
| 4550 | 8191
| | ~~~~
| 4551 | )>(
| | ~~~
| 4552 |
hold_count + 1
| |
~~~~~~~~~~~~~~
| 4553 | ))?(
| | ~~~~
| 4554 | 8191
| | ~~~~
| 4555 | ):(
| | ~~~
| | |
| | (49)
...to here
| 4556 |
hold_count + 1
| |
~~~~~~~~~~~~~~
| 4557 | ))
| | ~~
|......
| 4567 | if (hold_count)
| | ~
| | |
| | (50) following
‘false’ branch...
|......
| 4574 | b->bytes_used +=
read_input (p, bytes_avail - 1);
| |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (51)
...to here
| | (52)
calling ‘read_input’ from ‘load_buffer’
|
+--> ‘read_input’: events 53-57
|
| 4391 | read_input (char *dest,
idx_t max_n_bytes)
| | ^~~~~~~~~~
| | |
| | (53) entry to
‘read_input’
|......
| 4394 | if (max_n_bytes == 0)
| | ~
| | |
| | (54) following
‘false’ branch (when ‘max_n_bytes != 0’)...
| 4395 | return 0;
| 4396 | bytes_read =
safe_read (
| |
~~~~~~~~~~~
| | |
| | (55)
...to here
| 4397 |
0
| |
~
| 4398 |
, dest, max_n_bytes);
| |
~~~~~~~~~~~~~~~~~~~~
|......
| 4403 | if (bytes_read ==
((size_t) -1))
| | ~
| | |
| | (56) following
‘false’ branch (when ‘bytes_read != -1’)...
|......
| 4410 | return bytes_read;
| | ~~~~~~~~~~
| | |
| | (57) ...to
here
|
<------+
|
‘load_buffer’: events 58-59
|
| 4574 | b->bytes_used +=
read_input (p, bytes_avail - 1);
| |
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (58)
returning to ‘load_buffer’ from ‘read_input’
| 4575 | if (record_line_starts
(b) != 0)
| |
~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (59) calling
‘record_line_starts’ from ‘load_buffer’
|
+--> ‘record_line_starts’: events 60-65
|
| 4449 | record_line_starts
(struct buffer_record *b)
| | ^~~~~~~~~~~~~~~~~~
| | |
| | (60) entry to
‘record_line_starts’
|......
| 4454 | if (b->bytes_used ==
0)
| | ~
| | |
| | (61) following
‘false’ branch...
| 4455 | return 0;
| 4456 | lines = 0;
| | ~~~~~~~~~
| | |
| | (62) ...to here
|......
| 4465 | if (line_end ==
buffer_end)
| | ~
| | |
| | (63) following
‘false’ branch (when ‘line_end != buffer_end’)...
| 4466 | break;
| 4467 | line_length =
line_end - line_start + 1;
| |
~~~~~~~~~~~~~~~~~~~~~
| |
|
| |
(64) ...to here
| 4468 | keep_new_line (b,
line_start, line_length);
| |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (65) calling
‘keep_new_line’ from ‘record_line_starts’
|
+--> ‘keep_new_line’: events
66-68
|
| 4430 | keep_new_line
(struct buffer_record *b, char *line_start, idx_t line_len)
| | ^~~~~~~~~~~~~
| | |
| | (66) entry to
‘keep_new_line’
|......
| 4433 | if
(b->line_start ==
| | ~
| | |
| | (67)
following ‘false’ branch...
|......
| 4437 | if
(b->curr_line->used == 80)
| |
~~~~~~~~~~~~
| | |
| | (68)
...to here
|
<------+
|
‘record_line_starts’: events 69-72
|
| 4465 | if (line_end ==
buffer_end)
| | ~
| | |
| | (70) following
‘false’ branch (when ‘line_end != buffer_end’)...
| 4466 | break;
| 4467 | line_length =
line_end - line_start + 1;
| |
~~~~~~~~~~~~~~~~~~~~~
| |
|
| |
(71) ...to here
| 4468 | keep_new_line (b,
line_start, line_length);
| |
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (69) returning to
‘record_line_starts’ from ‘keep_new_line’
| | (72) calling
‘keep_new_line’ from ‘record_line_starts’
|
+--> ‘keep_new_line’: events
73-76
|
| 4430 | keep_new_line
(struct buffer_record *b, char *line_start, idx_t line_len)
| | ^~~~~~~~~~~~~
| | |
| | (73) entry to
‘keep_new_line’
|......
| 4433 | if
(b->line_start ==
| | ~
| | |
| | (74)
following ‘true’ branch...
|......
| 4436 |
b->line_start = b->curr_line = new_line_control ();
| |
~~~~~~~~~~~~~~~~~~~
| |
|
| |
(75) ...to here
| |
(76) calling ‘new_line_control’ from ‘keep_new_line’
|
+--> ‘new_line_control’:
events 77-78
|
| 4420 |
new_line_control (void)
| |
^~~~~~~~~~~~~~~~
| | |
| | (77)
entry to ‘new_line_control’
| 4421 | {
| 4422 | struct
line *p = xmalloc (sizeof *p);
| |
~~~~~~~~~~~~~~~~~~~
| |
|
| |
(78) allocated here
|
<------+
|
‘keep_new_line’: events
79-81
|
| 4436 |
b->line_start = b->curr_line = new_line_control ();
| |
^~~~~~~~~~~~~~~~~~~
| |
|
| |
(79) returning to ‘keep_new_line’ from ‘new_line_control’
| 4437 | if
(b->curr_line->used == 80)
| | ~
| | |
| | (80)
following ‘false’ branch...
|......
| 4442 | l =
b->curr_line;
| |
~~~~~~~~~~~~~~~~
| | |
| | (81) ...to
here
|
<------+
|
‘record_line_starts’: events 82-83
|
| 4465 | if (line_end ==
buffer_end)
| | ~
| | |
| | (83) following
‘true’ branch (when ‘line_end == buffer_end’)...
|......
| 4468 | keep_new_line (b,
line_start, line_length);
| |
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (82) returning to
‘record_line_starts’ from ‘keep_new_line’
|
‘record_line_starts’: event 84
|
|cc1:
| (84): ...to here
|
<------+
|
‘load_buffer’: events 85-88
|
| 4575 | if (record_line_starts
(b) != 0)
| |
~^~~~~~~~~~~~~~~~~~~~~~
| | ||
| | |(85) returning to
‘load_buffer’ from ‘record_line_starts’
| | (86) following
‘false’ branch...
|......
| 4582 | free_buffer (b);
| | ~~~~~~~~~~~~~~~
| | |
| | (87) ...to here
| | (88) ‘<unknown>’ leaks
here; was allocated at (78)
|
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2023-04-25 0:17 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-04-25 0:17 [Bug analyzer/109614] New: -Wanalyzer-use-after-free gets confused about a free function in Coreutils eggert at cs dot ucla.edu
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).