https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125237
Bug ID: 125237
Summary: Multiple libstdc++ in a process may cause locale facet
ID overlap
Product: gcc
Version: 16.1.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: libstdc++
Assignee: unassigned at gcc dot gnu.org
Reporter: blubban at gmail dot com
Target Milestone: ---
https://godbolt.org/z/P43vGdoev
This one has a really specific set of requirements to trigger.
- The executable and its dependencies must not use libstdc++
- libA must link libstdc++ dynamically
- libB must link libstdc++ statically
- both must be dlopen'd, libA before libB
- and both must use std::locale (possibly indirectly, for example via
std::istringstream)
If all of those happen, certain locale facets may start sharing facet IDs in
libB, causing segfaults and other mayhem whenever the program tries using them.
a.c:
#include <dlfcn.h>
int main() {
void* libfoo = dlopen("build/libfoo.so", RTLD_NOW);
void(*ggg)() = dlsym(libfoo, "ggg");
ggg();
void* libbar = dlopen("build/libbar.so", RTLD_NOW);
void(*gggg)() = dlsym(libbar, "gggg");
gggg();
}
b.cpp:
#include <locale>
extern "C"
void ggg() {
std::locale loc;
}
c.cpp:
#include <sstream>
#include <stdio.h>
#include <typeinfo>
#include <codecvt>
extern "C"
void gggg() {
std::locale ab;
const std::num_get<char>& ng = std::use_facet<std::num_get<char>>(ab);
const std::locale::facet* ngf = &ng;
printf("dynamic cast to self: %p\n", dynamic_cast<const
std::num_get<char>*>(ngf));
printf("name should be std::num_get<char, std::istreambuf_iterator<char,
std::char_traits<char>>>: %s\n", typeid(ng).name());
printf("should not be the same: %d %d\n", std::num_get<char>::id._M_id(),
std::codecvt<wchar_t, char, std::mbstate_t>::id._M_id());
std::string a="12345";
std::istringstream ss(a);
int i=66666;
printf("parsing integer should not segfault:\n");
fflush(stdout);
ss>>i;
printf("should be 12345: %d\n", i);
}
Compile flags:
mkdir build
gcc a.c -o build/a.out
g++ b.cpp -shared -fPIC -obuild/libfoo.so
g++ c.cpp -shared -fPIC -obuild/libbar.so -static-libstdc++
build/a.out
Expected:
dynamic cast to self: 0x7eff24463940
name should be std::num_get<char, std::istreambuf_iterator<char,
std::char_traits<char>>>:
St7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE
should not be the same: 3 15
parsing integer should not segfault:
should be 12345: 12345
Actual:
dynamic cast to self: (nil)
name should be std::num_get<char, std::istreambuf_iterator<char,
std::char_traits<char>>>: St7codecvtIwc11__mbstate_tE
should not be the same: 3 3
parsing integer should not segfault:
Segmentation fault