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

Reply via email to