https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127896
Bug ID: 127896
Summary: -Wanalyzer-out-of-bounds false positives in Emacs
array of size 5
Product: gcc
Version: 16.2.1
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 65845
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=65845&action=edit
Compile this with "gcc -S -fanalyzer -O2" to see the bug
This is gcc (GCC) 16.2.1 20260819 (Red Hat 16.2.1-2) on x86-64. Compile the
attached file (derived from current Emacs master) with:
gzip -d t.i.gz
gcc -S -fanalyzer -O2 t.i
The output starts as follows but then goes on for much longer in the same vein.
The diagnostics are obviously wrong, as i is obviously in the range 0..4
because props_idx is in the range 0..5 and this can easily be determined by
static analysis of the containing function.
I plan to work around the problem by disabling this warning when compiling the
affected source file.
----
t.i: In function ‘smc_save_yourself_CB’:
t.i:115976:19: warning: stack-based buffer over-read [CWE-126]
[-Wanalyzer-out-of-bounds]
115976 | xfree (props[i]->type);
| ~~~~~^~~
‘smc_save_yourself_CB’: events 1-3
│
│115827 | smc_save_yourself_CB (SmcConn smcConn,
│ | ^~~~~~~~~~~~~~~~~~~~
│ | |
│ | (1) entry to ‘smc_save_yourself_CB’
│.......
│115840 | SmProp *props[5];
│ | ~~~~~
│ | |
│ | (2) capacity: 40 bytes
│.......
│115853 | if (! STRINGP (globals.f_Vinvocation_name) || ! STRINGP
(user_login_name))
│ | ~
│ | |
│ | (3) following ‘false’ branch... ─>─┐
│ | │
│
‘smc_save_yourself_CB’: event 4
│
│ | │
│ |┌────────────────────────────────────────┘
│115853 |│ if (! STRINGP (globals.f_Vinvocation_name) || ! STRINGP
(user_login_name))
│ |│ ^
│ |│ |
│ |└─────────────────────────────────────────────────>(4) inlined
call to ‘STRINGP’ from ‘smc_save_yourself_CB’
│
└──> ‘STRINGP’: event 5
│
│20049 | return TAGGEDP (x, Lisp_String);
│ | ^
│ | |
│ | (5) inlined call to ‘TAGGEDP’ from ‘STRINGP’
│
└──> ‘TAGGEDP’: event 6
│
│12775 | return (XTYPE (a) == (tag));
│ | ^
│ | |
│ | (6) inlined call to ‘XTYPE’ from ‘TAGGEDP’
│
└──> ‘XTYPE’: event 7
│
│12758 | return ((enum Lisp_Type) (XLI (a) &
~(((0x7fffffffffffffffL
│ | ^
│ | |
│ | (7) inlined call
to ‘XLI’ from ‘XTYPE’
│
└──> ‘XLI’: event 8
│
│12737 | return ((EMACS_INT) (o));
│ | ~^~~~~~~~~~~~~~~~
│ | |
│ | (8) ...to here
│
<───────────────────────────┘
│
‘smc_save_yourself_CB’: events 9-16
│
│115853 | if (! STRINGP (globals.f_Vinvocation_name) || ! STRINGP
(user_login_name))
│ |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
│ | |
│ | (9) following
‘false’ branch... ─>─┐
│ |
│
│.......
│ |
│
│
|┌────────────────────────────────────────────────────────────────────────────────┘
│115857 |│ props[props_idx] = &prop_ptr[props_idx];
│ |│ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
│ |│ |
│ |└──────────────────>(10) ...to here
│.......
│115925 | if (
│ | ~
│ | |
│ | (11) following ‘false’ branch... ─>─┐
│ | │
│.......
│ | │
│ |┌─────────────────────────────────────────┘
│115935 |│ props[props_idx]->num_vals = i;
│ |│ ~~~~~~~~~~~~~~~~
│ |│ |
│ |└──────>(12) ...to here
│.......
│115950 | if (cwd)
│ | ~
│ | |
│ | (13) following ‘false’ branch (when ‘cwd’ is NULL)... ─>─┐
│ | │
│.......
│ | │
│ |┌──────────────────────────────────────────────────────────────┘
│115959 |│ for (i = 1; i < initial_argc; ++i)
│ |│ ~~~
│ |│ |
│ |└─>(14) ...to here
│.......
│115974 | for (i = 0; i < props_idx; ++i)
│ | ~~~~~~~~~~~~~
│ | |
│ | (15) following ‘true’ branch (when ‘i <
props_idx’)... ─>─┐
│ |
│
│ |
│
│
|┌──────────────────────────────────────────────────────────────────────────┘
│115975 |│ {
│115976 |│ xfree (props[i]->type);
│ |│ ~~~~~~~~
│ |│ |
│ |└─────────────────>(16) ...to here
│
‘smc_save_yourself_CB’: events 17-18
│
│115974 | for (i = 0; i < props_idx; ++i)
│ | ~~^~~~~~~~~~~
│ | |
│ | (17) following ‘true’ branch (when ‘i <
props_idx’)... ─>─┐
│ |
│
│ |
│
│
|┌──────────────────────────────────────────────────────────────────────────┘
│115975 |│ {
│115976 |│ xfree (props[i]->type);
│ |│ ~~~~~~~~
│ |│ |
│ |└─────────────────>(18) ...to here
│
‘smc_save_yourself_CB’: events 19-20
│
│115974 | for (i = 0; i < props_idx; ++i)
│ | ~~^~~~~~~~~~~
│ | |
│ | (19) following ‘true’ branch (when ‘i <
props_idx’)... ─>─┐
│ |
│
│ |
│
│
|┌──────────────────────────────────────────────────────────────────────────┘
│115975 |│ {
│115976 |│ xfree (props[i]->type);
│ |│ ~~~~~~~~
│ |│ |
│ |└─────────────────>(20) ...to here
│
‘smc_save_yourself_CB’: events 21-22
│
│115974 | for (i = 0; i < props_idx; ++i)
│ | ~~^~~~~~~~~~~
│ | |
│ | (21) following ‘true’ branch (when ‘i <
props_idx’)... ─>─┐
│ |
│
│ |
│
│
|┌──────────────────────────────────────────────────────────────────────────┘
│115975 |│ {
│115976 |│ xfree (props[i]->type);
│ |│ ~~~~~~~~
│ |│ |
│ |└─────────────────>(22) ...to here
│
‘smc_save_yourself_CB’: events 23-24
│
│115974 | for (i = 0; i < props_idx; ++i)
│ | ~~^~~~~~~~~~~
│ | |
│ | (23) following ‘true’ branch (when ‘i <
props_idx’)... ─>─┐
│ |
│
│ |
│
│
|┌──────────────────────────────────────────────────────────────────────────┘
│115975 |│ {
│115976 |│ xfree (props[i]->type);
│ |│ ~~~~~~~~
│ |│ |
│ |└─────────────────>(24) ...to here
│
‘smc_save_yourself_CB’: events 25-27
│
│115974 | for (i = 0; i < props_idx; ++i)
│ | ~~^~~~~~~~~~~
│ | |
│ | (25) following ‘true’ branch (when ‘i <
props_idx’)... ─>─┐
│ |
│
│ |
│
│
|┌──────────────────────────────────────────────────────────────────────────┘
│115975 |│ {
│115976 |│ xfree (props[i]->type);
│ |│ ~~~~~~~~
│ |│ |
│ |└─────────────────>(26) ...to here
│ | (27) ⚠️ out-of-bounds read from byte 40 till
byte 47 but ‘props’ ends at byte 40
│
t.i:115976:19: note: read of 8 bytes from after the end of ‘props’
115976 | xfree (props[i]->type);
| ~~~~~^~~
t.i:115976:19: note: valid subscripts for ‘props’ are ‘[0]’ to ‘[4]’
┌───────────────────────────────────┐
│read of ‘struct SmProp *’ (8 bytes)│
└───────────────────────────────────┘
^
│
│
┌───────────┬───────────┬────────────┐┌───────────────────────────────────┐
│ [0] │ ... │ [4] ││ │
├───────────┴───────────┴────────────┤│ after valid range │
│‘props’ (type: ‘struct SmProp *[5]’)││ │
└────────────────────────────────────┘└───────────────────────────────────┘
├─────────────────┬──────────────────┤├─────────────────┬─────────────────┤
│ │
╭───────┴──────╮ ╭───────────┴───────────╮
│size: 40 bytes│ │⚠️ over-read of 8 bytes│
╰──────────────╯ ╰───────────────────────╯