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!