https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124665
Bug ID: 124665
Summary: -Wstringop-overflow false positive when inlining
Product: gcc
Version: 14.3.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c
Assignee: unassigned at gcc dot gnu.org
Reporter: jiangxuezhi2 at huawei dot com
Target Milestone: ---
I’m encountering a confusing -Wstringop-overflow warning that only appears when
a function gets inlined, but disappears with -fno-inline. This seems like a
static analyzer false positive after inlining.
Here’s what my code essentially does (simplified):
~~~c
static void test2(UINT32 startSn, UINT32 endSn, UINT8 *appHdr)
{
CommonAppHdrStru *pdcpAppHdr = (CommonAppHdrStru*)appHdr;
UINT8 *data = appHdr;
pdcpAppHdr->firstOctetOfSequenceNum = 0;
pdcpAppHdr->secondOctetOfSequenceNum = 0;
pdcpAppHdr->npduNum = 0;
pdcpAppHdr->nextExtensionHdrType = (UINT8)0x84;
offset += sizeof(CommonAppHdrStru);
rsvd = data + offset;
*rsvd = 0;
nextType = data + offset + sizeof(UINT8);
*nextType = 0;
}
static void test1(...)
{
RbdStru *sduRbd = 0L;
sduRbd->offset = (UINT16)(192);
sduRbd->length = (UINT16)(sizeof(CommonAppHdrStru));
CommonDlSduStru *commHdr = (CommonDlSduStru*)(L2OS_GetRbdPayload(sduRbd));
test2(startSn, endSn, (UINT8*)&commHdr->pdcpAppHdr);
}
~~~
The warning:
In function 'test2',
warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=]
...: In function 'test1':
...:244:22: note: at offset [22, 34] into destination object 'pdcpAppHdr' of
size 4
...:244:22: note: at offset [22, 34] into destination object 'pdcpAppHdr' of
size 4
In function 'test2',
inlined from 'test1' at ...
warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=]
...: In function 'test1':
...:244:22: note: at offset [23, 35] into destination object 'pdcpAppHdr' of
size 4
...:244:22: note: at offset [23, 35] into destination object 'pdcpAppHdr' of
size 4
When test2() receives a UINT8* buffer pointer that we temporarily cast to a
smaller CommonAppHdrStru* (size 4) for structured field access, but then
continue using the original UINT8* pointer for byte-level arithmetic at larger
offsets (22+).
When inlining happens, GCC’s analyzer seems to incorrectly constrain the entire
buffer to the smaller 4-byte structure size from the cast, losing track of the
fact that we’re actually working with a much larger buffer from
L2OS_GetRbdPayload(sduRbd).
I’m wondering if this is a known limitation in how GCC tracks pointer
provenance across type casts during inlining, and whether there are suggested
annotations or if this represents a gap in the compute_objsize logic that needs
improvement.