https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89720
Bug ID: 89720
Summary: [9 Regression] Spurious -Warray-bounds warning
Product: gcc
Version: 9.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: steinar+gcc at gunderson dot no
Target Milestone: ---
Hi,
The following is a reduced test case from MySQL:
char func(long j)
{
char h[65536];
char *copy = h + (j & 0xffffffff3fffffffL);
return *(copy - 6);
}
GCC 9-20190302-1 from Debian gives, with -O2:
test.cpp: In function ‘char func(long int)’:
test.cpp:5:20: warning: array subscript [-3221225479, -6] is outside array
bounds of ‘char [65536]’ [-Warray-bounds]
5 | return *(copy - 6);
| ^
test.cpp:3:8: note: while referencing ‘h’
3 | char h[65536];
| ^
I believe there's some sort of signedness confusion here; the actual offset can
certainly be far above -6.
There's an additional problem in the un-reduced case, in that the diagnostic is
very hard to understand; the reference happens several levels away from the
definition of the buffer, with no indication about the call stack:
In file included from
/home/sesse/nmu/mysql-server/storage/innobase/include/mach0data.h:319,
from
/home/sesse/nmu/mysql-server/storage/innobase/include/data0type.ic:34,
from
/home/sesse/nmu/mysql-server/storage/innobase/include/data0type.h:531,
from
/home/sesse/nmu/mysql-server/storage/innobase/include/data0data.h:38,
from
/home/sesse/nmu/mysql-server/storage/innobase/include/que0que.h:36,
from
/home/sesse/nmu/mysql-server/storage/innobase/include/api0misc.h:41,
from
/home/sesse/nmu/mysql-server/storage/innobase/api/api0api.cc:41:
/home/sesse/nmu/mysql-server/storage/innobase/include/mach0data.ic: In function
‘ib_err_t ib_cursor_delete_row(ib_crsr_t)’:
/home/sesse/nmu/mysql-server/storage/innobase/include/mach0data.ic:67:26:
warning: array subscript [-3221225479, -6] is outside array bounds of ‘unsigned
char [65536]’ [-Warray-bounds]
67 | return ((uint8_t)(b[0]));
| ^
The function with the warning on reads:
UNIV_INLINE
uint8_t mach_read_from_1(const byte *b) {
ut_ad(b); // This is a custom assert macro.
return ((uint8_t)(b[0]));
}
and the chain from ib_cursor_delete_row() to mach_read_from_1() is difficult to
track own manually. Having some sort of trace here would be very useful.