https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116449
Bug ID: 116449
Summary: Miscompilation with UBSAN
Product: gcc
Version: 15.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: sanitizer
Assignee: unassigned at gcc dot gnu.org
Reporter: sirl at gcc dot gnu.org
CC: dodji at gcc dot gnu.org, dvyukov at gcc dot gnu.org,
jakub at gcc dot gnu.org, kcc at gcc dot gnu.org
Target Milestone: ---
Hi,
compiling this example with
g++-trunk -c -fsanitize=undefined test.cpp -O2 -W -Wall
class C
{
public:
void P(int);
void IP();
int parr[16];
};
typedef void (C::*fp)();
typedef struct arr_t
{
fp func;
} arr_t;
static arr_t farr[1] =
{
{ &C::IP },
};
void C::P(int c)
{
((*this).*farr[parr[c]].func)();
}
results in this warning
test.cpp: In member function 'void C::P(int)':
test.cpp:23:31: warning: '<anonymous>' may be used uninitialized
[-Wmaybe-uninitialized]
23 | ((*this).*farr[parr[c]].func)();
| ~~~~~~~~~~~~^
But the real problem is miscompilation that starts already in the gimple dump:
void C::P (struct C * const this, int c)
{
void C::<T40d> (struct C *) * iftmp.0;
int D.3291;
int D.3294;
struct C * D.3296;
D.3291 = this->parr[c];
.UBSAN_BOUNDS (0B, D.3291, 1);
_1 = farr[D.3291].func.__pfn;
_2 = (long int) _1;
_3 = _2 & 1;
if (_3 == 0) goto <D.3292>; else goto <D.3293>;
<D.3292>:
D.3294 = this->parr[c];
.UBSAN_BOUNDS (0B, D.3294, 1);
iftmp.0 = farr[D.3294].func.__pfn;
goto <D.3295>;
<D.3293>:
.UBSAN_BOUNDS (0B, D.3294, 1);
_4 = farr[D.3294].func.__delta;
_5 = (sizetype) _4;
_6 = this + _5;
_7 = MEM[(int (*) () * *)_6];
.UBSAN_BOUNDS (0B, D.3294, 1);
_8 = farr[D.3294].func.__pfn;
_9 = (long int) _8;
_10 = _9 - 1;
_11 = (sizetype) _10;
_12 = _7 + _11;
iftmp.0 = *_12;
<D.3295>:
iftmp.1_13 = iftmp.0;
.UBSAN_BOUNDS (0B, D.3294, 1);
_14 = farr[D.3294].func.__delta;
_15 = (sizetype) _14;
D.3296 = this + _15;
.UBSAN_NULL (D.3296, 4B, 4);
iftmp.1_13 (D.3296);
}
As you can see ".UBSAN_BOUNDS (0B, D.3294, 1)" check is repeated multiple
times, but in the <D.3293> branch D.3294 is not initialized at all.
This causes wrong out-of-bounds reports and eventually even application crashes
(seen in the original testcase).
Tested with trunk@r15-3043, but it seems all versions since at least GCC-10 are
affected.