https://gcc.gnu.org/bugzilla/show_bug.cgi?id=122380
Bug ID: 122380
Summary: std::variant with std::vectors of differing types may
lead to double frees
Product: gcc
Version: 15.2.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: libstdc++
Assignee: unassigned at gcc dot gnu.org
Reporter: eigengrau at vm86 dot se
Target Milestone: ---
Created attachment 62612
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=62612&action=edit
repro.cc
GCC 15.2.0 produces a crashing program on ARM with -O2 or -O3 due to a
double-free caused in get_dvec() in the attached reproducer with -std=gnu++20.
It works as expected when compiled with GCC 14.3.0.
It looks like the stores in get_dvec() from the inlined move-assignment
operator of std::vector, that are supposed to zero the fields of the moved-from
vector, are eliminated at some point. As _M_impl._M_start is non-zero, the
destructor of the moved-from vector then invokes operator delete on
_M_impl._M_start; this leaves the destination vector `entries` with a dangling
pointer which is freed again when the vector is destroyed.
This is about as minimal a runnable example as I could manage to reduce it to
(except for main() which can be removed if you don't care about running it).
The following things appear to negate the bug:
- compiling with -O1, -Og, or -Os;
- compiling with -std=gnu++17;
- compiling with -D_GLIBCXX_DEBUG=1;
- compiling with -fno-strict-aliasing (but I can't see anything in the
example that obviously runs afoul of aliasing rules).
Output from -v attached in `gcc-v.txt`. This is from GCC 15.2.0 built via Poky
Whinlatter which is lightly patched, but it generates the same assembly for
get_dvec() as vanilla GCC 15.2.0; see <https://gcc.godbolt.org/z/s6G1MsWTc>.