https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106709
Bug ID: 106709
Summary: GCC incorrectly warns about stringop-overread
Product: gcc
Version: 12.2.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c
Assignee: unassigned at gcc dot gnu.org
Reporter: ljrk at ljrk dot org
Target Milestone: ---
Created attachment 53489
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=53489&action=edit
Minimal Working/Reproducing Example
GCC incorrectly warns with default flags and optimization level -O2 about a
number of buffer overruns, in this example from `libmdigest` as part of the
schilytools in a call to `SHA1Update` at
https://codeberg.org/schilytools/schilytools/src/branch/master/libmdigest/sha1.c#L251:
==> COMPILING "OBJ/x86_64-linux-gcc/sha1.o"
In function 'SHA1Update',
inlined from 'SHA1Pad' at sha1.c:251:2:
sha1.c:228:25: warning: 'SHA1Transform' reading 64 bytes from a region
of size 1 [-Wstringop-overread]
228 | SHA1Transform(context->state, (UInt8_t
*)&data[i]);
|
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sha1.c:228:25: note: referencing argument 2 of type 'const uint8_t[64]'
{aka 'const unsigned char[64]'}
In this example we have the following code snippet in `SHA1Pad`:
SHA1Update(context, /* data: */ (UInt8_t *)"\200", /* len: */
1);
with the inlined update function being:
j = (size_t)((context->count[0] >> 3) & 63);
/* ... */
if ((j + len) > 63) {
/* ... */ i = 64-j /*...*/;
SHA1Transform(context->state, context->buffer);
for (; i + 63 < len; i += 64)
SHA1Transform(context->state, (UInt8_t
*)&data[i]);
j = 0;
} else /* ... */
Depending on the value of `count[0]`, both `j` may be up to 63 (if `count[0]`
is 0x3f00 or more). Only in this case, with `len = 1` from `SHA1Update`, we
would enter this code block and correctly copy `i = 64-63 = 1` bytes from the 1
byte data buffer. The loop would start with `i+63 = 1+63 < len = 1` and thus
not call `SHA1Transform` in any case.
Setting `j = 63` directly silences the warning, so it seems like GCC can't keep
track of `j <= 63`.
I've attached a minimized mwe.c as well:
$ gcc -c -O2 -o mwe.o mwe.c
In function ‘mwe2’,
inlined from ‘mwe’ at mwe.c:17:2:
mwe.c:11:25: warning: ‘mwe3’ reading 64 bytes from a region of size 1
[-Wstringop-overread]
11 | mwe3((unsigned char*)&data[i]);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mwe.c:11:25: note: referencing argument 1 of type ‘const unsigned
char[64]’
mwe.c: In function ‘mwe’:
mwe.c:3:13: note: in a call to function ‘mwe3’
3 | extern void mwe3(const unsigned char buffer[64]);
| ^~~~
$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-linux-gnu/12.2.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: /build/gcc/src/gcc/configure
--enable-languages=c,c++,ada,fortran,go,lto,objc,obj-c++,d --enable-bootstrap
--prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man
--infodir=/usr/share/info --with-bugurl=https://bugs.archlinux.org/
--with-build-config=bootstrap-lto --with-linker-hash-style=gnu
--with-system-zlib --enable-__cxa_atexit --enable-cet=auto
--enable-checking=release --enable-clocale=gnu --enable-default-pie
--enable-default-ssp --enable-gnu-indirect-function --enable-gnu-unique-object
--enable-libstdcxx-backtrace --enable-link-serialization=1
--enable-linker-build-id --enable-lto --enable-multilib --enable-plugin
--enable-shared --enable-threads=posix --disable-libssp --disable-libstdcxx-pch
--disable-werror
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 12.2.0 (GCC)
It seems like this bug is related to
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105424 but I'm not sure. If so,
feel free to close it.
Thanks for maintaining this great piece of software!