Valgrind reports use-after-free for a translated interned string during Python init
Description
Starting a 6.0.8 build under valgrind reports a use-after-free during startup:
==5438== Invalid read of size 4
==5438== at 0x6598D83: UnknownInlinedFun (obmalloc.c:1420)
==5438== by 0x6598D83: UnknownInlinedFun (obmalloc.c:1866)
==5438== by 0x6598D83: _PyObject_Free (obmalloc.c:1920)
==5438== by 0x6584651: dictresize.lto_priv.0 (dictobject.c:1285)
==5438== by 0x6589C6F: UnknownInlinedFun (dictobject.c:1040)
==5438== by 0x6589C6F: PyDict_SetDefault (dictobject.c:2964)
==5438== by 0x65F56EF: PyUnicode_InternInPlace (unicodeobject.c:15609)
==5438== by 0x65F57AC: PyUnicode_InternFromString (unicodeobject.c:15645)
==5438== by 0x6663197: UnknownInlinedFun (typeobject.c:7572)
==5438== by 0x6663197: UnknownInlinedFun (object.c:1736)
==5438== by 0x6663197: UnknownInlinedFun (pylifecycle.c:588)
==5438== by 0x6663197: pycore_interp_init.lto_priv.0 (pylifecycle.c:725)
==5438== by 0x6772E3F: UnknownInlinedFun (pylifecycle.c:766)
==5438== by 0x6772E3F: pyinit_core.constprop.0 (pylifecycle.c:927)
==5438== by 0x6667700: UnknownInlinedFun (pylifecycle.c:1134)
==5438== by 0x6667700: Py_InitializeFromConfig (pylifecycle.c:1119)
==5438== by 0x6667AEB: Py_InitializeEx (pylifecycle.c:1172)
==5438== by 0x6D9D88: SCRIPTING::SCRIPTING() (in /usr/local/bin/kicad)
==5438== by 0x488184: PGM_BASE::InitPgm(bool, bool) (in /usr/local/bin/kicad)
==5438== by 0x3AE58E: PGM_KICAD::OnPgmInit() (in /usr/local/bin/kicad)
==5438== Address 0xaf92020 is 96 bytes inside a block of size 160 free'd
==5438== at 0x4839EAB: operator delete(void*) (vg_replace_malloc.c:584)
==5438== by 0x534656E: deallocate (new_allocator.h:128)
==5438== by 0x534656E: deallocate (alloc_traits.h:136)
==5438== by 0x534656E: _M_destroy (basic_string.h:237)
==5438== by 0x534656E: _M_dispose (basic_string.h:232)
==5438== by 0x534656E: ~basic_string (basic_string.h:658)
==5438== by 0x534656E: ~wxString (string.h:393)
==5438== by 0x534656E: ~wxStringToStringHashMap_wxImplementation_Pair (hashmap.h:749)
==5438== by 0x534656E: ~Node (hashmap.h:749)
==5438== by 0x534656E: wxStringToStringHashMap_wxImplementation_HashTable::DeleteNode(_wxHashTable_NodeBase*) (hashmap.h:749)
==5438== by 0x53CCCDF: _wxHashTableBase2::DeleteNodes(unsigned long, _wxHashTable_NodeBase**, void (*)(_wxHashTable_NodeBase*)) (hashmap.cpp:106)
==5438== by 0x542314C: clear (hashmap.h:749)
==5438== by 0x542314C: ~wxStringToStringHashMap_wxImplementation_HashTable (hashmap.h:749)
==5438== by 0x542314C: ~wxStringToStringHashMap (hashmap.h:749)
==5438== by 0x542314C: ~wxMsgCatalog (translation.h:61)
==5438== by 0x542314C: wxTranslations::~wxTranslations() (translation.cpp:1436)
==5438== by 0x53CE704: wxLocale::~wxLocale() (intl.cpp:1037)
==5438== by 0x53CE79E: wxLocale::~wxLocale() (intl.cpp:1058)
==5438== by 0x48AB3B: PGM_BASE::SetLanguage(wxString&, bool) (in /usr/local/bin/kicad)
==5438== by 0x487135: PGM_BASE::InitPgm(bool, bool) (in /usr/local/bin/kicad)
==5438== by 0x3AE58E: PGM_KICAD::OnPgmInit() (in /usr/local/bin/kicad)
==5438== by 0x3B14C3: APP_KICAD::OnInit() (in /usr/local/bin/kicad)
==5438== by 0x53CDA71: wxEntry(int&, wchar_t**) (init.cpp:490)
==5438== by 0x385827: main (in /usr/local/bin/kicad)
==5438== Block was alloc'd at
==5438== at 0x4838DEF: operator new(unsigned long) (vg_replace_malloc.c:342)
==5438== by 0x3D27CE: void std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >::_M_construct<wchar_t*>(wchar_t*, wchar_t*, std::forward_iterator_tag) (in /usr/local/bin/kicad)
==5438== by 0x5423EAC: _M_construct_aux<wchar_t*> (basic_string.h:247)
==5438== by 0x5423EAC: _M_construct<wchar_t*> (basic_string.h:266)
==5438== by 0x5423EAC: basic_string (basic_string.h:451)
==5438== by 0x5423EAC: wxString (string.h:1220)
==5438== by 0x5423EAC: wxStringToStringHashMap_wxImplementation_Pair (hashmap.h:749)
==5438== by 0x5423EAC: Node (hashmap.h:749)
==5438== by 0x5423EAC: CreateNode (hashmap.h:749)
==5438== by 0x5423EAC: GetOrCreateNode (hashmap.h:749)
==5438== by 0x5423EAC: operator[] (hashmap.h:749)
==5438== by 0x5423EAC: wxMsgCatalogFile::FillHash(wxStringToStringHashMap&, wxString const&) const (translation.cpp:1277)
==5438== by 0x542D5A7: wxMsgCatalog::CreateFromFile(wxString const&, wxString const&) (translation.cpp:1332)
==5438== by 0x542E335: wxFileTranslationsLoader::LoadCatalog(wxString const&, wxString const&) (translation.cpp:1905)
==5438== by 0x5429F5A: wxTranslations::LoadCatalog(wxString const&, wxString const&, wxString const&) (translation.cpp:1560)
==5438== by 0x542A633: wxTranslations::AddCatalog(wxString const&, wxLanguage) (translation.cpp:1522)
==5438== by 0x4852FF: PGM_BASE::SetDefaultLanguage(wxString&) (in /usr/local/bin/kicad)
==5438== by 0x487059: PGM_BASE::InitPgm(bool, bool) (in /usr/local/bin/kicad)
==5438== by 0x3AE58E: PGM_KICAD::OnPgmInit() (in /usr/local/bin/kicad)
==5438== by 0x3B14C3: APP_KICAD::OnInit() (in /usr/local/bin/kicad)
==5438== by 0x53CDA71: wxEntry(int&, wchar_t**) (init.cpp:490)
It seems that a translated string is given as a char const *
to the Python interpreter at some (earlier) point with the promise that its lifetime was infinite, and the interpreter decides to intern this string and reuse it subsequently.
Steps to reproduce
- Start under valgrind. No action inside the program needed, so it can be closed immediately.
KiCad Version
Application: KiCad
Version: (6.0.8), debug build
Libraries:
wxWidgets 3.0.5
libcurl/7.74.0 GnuTLS/3.7.1 zlib/1.2.11 brotli/1.0.9 libidn2/2.3.0 libpsl/0.21.0 (+libidn2/2.3.0) libssh2/1.9.0 nghttp2/1.43.0 librtmp/2.3
Platform: Linux 5.10.0-18-amd64 x86_64, 64 bit, Little endian, wxGTK, , tty
Build Info:
Date: Oct 8 2022 08:09:34
wxWidgets: 3.0.5 (wchar_t,wx containers,compatible with 2.8) GTK+ 3.24
Boost: 1.74.0
OCC: 7.5.1
Curl: 7.74.0
ngspice: 34
Compiler: GCC 10.2.1 with C++ ABI 1014
Build settings:
KICAD_USE_OCC=ON
KICAD_SPICE=ON
KICAD_STDLIB_DEBUG=OFF
KICAD_STDLIB_LIGHT_DEBUG=OFF
KICAD_SANITIZE_ADDRESS=OFF
KICAD_SANITIZE_THREADS=OFF