https://bugs.kde.org/show_bug.cgi?id=463052
Bug ID: 463052 Summary: Krita crashes on double free when closing application Classification: Applications Product: krita Version: 5.1.3 Platform: Debian testing OS: Linux Status: REPORTED Severity: normal Priority: NOR Component: * Unknown Assignee: krita-bugs-n...@kde.org Reporter: bernha...@mailbox.org Target Milestone: --- I tried investigating on Debian Bug https://bugs.debian.org/1025104. And I could reproduce it in a i386 and amd64 VM. The crash happens when main is already left and the exit handlers get executed: Thread 1 received signal SIGSEGV, Segmentation fault. 0x00007fd65c0bef73 in KoColorProfileStorage::Private::~Private (this=0x557d2d687090, __in_chrg=<optimized out>) at ./libs/pigment/KoColorProfileStorage.cpp:42 42 delete p; 1: x/i $pc => 0x7fd65c0bef73 <_ZN21KoColorProfileStorage7PrivateD2Ev+787>: call *0x8(%rax) (rr) bt #0 0x00007fd65c0bef73 in KoColorProfileStorage::Private::~Private() (this=0x557d2d687090, __in_chrg=<optimized out>) at ./libs/pigment/KoColorProfileStorage.cpp:42 #1 0x00007fd65c0bcf71 in QScopedPointerDeleter<KoColorProfileStorage::Private>::cleanup(KoColorProfileStorage::Private*) (pointer=0x557d2d687090) at /usr/include/x86_64-linux-gnu/qt5/QtCore/qscopedpointer.h:60 #2 QScopedPointerDeleter<KoColorProfileStorage::Private>::cleanup(KoColorProfileStorage::Private*) (pointer=0x557d2d687090) at /usr/include/x86_64-linux-gnu/qt5/QtCore/qscopedpointer.h:52 #3 QScopedPointer<KoColorProfileStorage::Private, QScopedPointerDeleter<KoColorProfileStorage::Private> >::~QScopedPointer() (this=<optimized out>, __in_chrg=<optimized out>) at /usr/include/x86_64-linux-gnu/qt5/QtCore/qscopedpointer.h:107 #4 KoColorProfileStorage::~KoColorProfileStorage() (this=<optimized out>, __in_chrg=<optimized out>) at ./libs/pigment/KoColorProfileStorage.cpp:56 #5 0x00007fd65c0b531d in KoColorSpaceRegistry::Private::~Private() (this=0x557d2d563d40, __in_chrg=<optimized out>) at ./libs/pigment/KoColorSpaceRegistry.cpp:42 #6 KoColorSpaceRegistry::~KoColorSpaceRegistry() (this=0x7fd65c3841f0 <(anonymous namespace)::Q_QGS_s_instance::innerFunction()::holder>, __in_chrg=<optimized out>) at ./libs/pigment/KoColorSpaceRegistry.cpp:232 #7 0x00007fd65c0b5519 in Holder::~Holder() (this=<optimized out>, __in_chrg=<optimized out>) at ./libs/pigment/KoColorSpaceRegistry.cpp:39 #8 0x00007fd65e2fa435 in __run_exit_handlers (status=0, listp=0x7fd65e48e820 <__exit_funcs>, run_list_atexit=run_list_atexit@entry=true, run_dtors=run_dtors@entry=true) at ./stdlib/exit.c:113 #9 0x00007fd65e2fa5aa in __GI_exit (status=<optimized out>) at ./stdlib/exit.c:143 #10 0x00007fd65e2e3191 in __libc_start_call_main (main=main@entry=0x557d2c4544c0 <main(int, char**)>, argc=argc@entry=1, argv=argv@entry=0x7ffdc9b620f8) at ../sysdeps/nptl/libc_start_call_main.h:74 #11 0x00007fd65e2e3245 in __libc_start_main_impl (main=0x557d2c4544c0 <main(int, char**)>, argc=1, argv=0x7ffdc9b620f8, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7ffdc9b620e8) at ../csu/libc-start.c:381 #12 0x0000557d2c458271 in _start () (rr) list 30 ~Private() 31 { 32 Q_FOREACH (KoColorProfile *p, profileMap) { 33 profileUniqueIdMap.remove(p->uniqueId()); 34 delete p; 35 } 36 profileMap.clear(); 37 Q_FOREACH (KoColorProfile *p, profileUniqueIdMap) { 38 delete p; 39 } 40 profileUniqueIdMap.clear(); 41 Q_FOREACH(KoColorProfile *p, duplicates) { 42 delete p; 43 } 44 duplicates.clear(); 45 } Valgrind brought this to the point as double free: ==6079== Invalid read of size 4 ==6079== at 0x7AC33A8: KoColorProfileStorage::Private::~Private() (KoColorProfileStorage.cpp:42) ==6079== by 0x7AC12D2: cleanup (qscopedpointer.h:60) ==6079== by 0x7AC12D2: cleanup (qscopedpointer.h:52) ==6079== by 0x7AC12D2: ~QScopedPointer (qscopedpointer.h:107) ==6079== by 0x7AC12D2: KoColorProfileStorage::~KoColorProfileStorage() (KoColorProfileStorage.cpp:56) ==6079== by 0x7AB8CE6: ~Private (KoColorSpaceRegistry.cpp:42) ==6079== by 0x7AB8CE6: KoColorSpaceRegistry::~KoColorSpaceRegistry() (KoColorSpaceRegistry.cpp:232) ==6079== by 0x7AB8F07: (anonymous namespace)::Q_QGS_s_instance::innerFunction()::Holder::~Holder() (KoColorSpaceRegistry.cpp:39) ==6079== by 0x70D7B5A: __run_exit_handlers (exit.c:89) ==6079== by 0x70D7CB0: exit (exit.c:143) ==6079== by 0x70BF2A0: (below main) (libc_start_call_main.h:74) ==6079== Address 0xdfb8a18 is 0 bytes inside a block of size 8 free'd ==6079== at 0x48436C7: operator delete(void*, unsigned int) (vg_replace_malloc.c:929) ==6079== by 0x7C6A74B: KoDummyColorProfile::~KoDummyColorProfile() (KoDummyColorProfile.cpp:16) ==6079== by 0x7AC314B: KoColorProfileStorage::Private::~Private() (KoColorProfileStorage.cpp:34) ==6079== by 0x7AC12D2: cleanup (qscopedpointer.h:60) ==6079== by 0x7AC12D2: cleanup (qscopedpointer.h:52) ==6079== by 0x7AC12D2: ~QScopedPointer (qscopedpointer.h:107) ==6079== by 0x7AC12D2: KoColorProfileStorage::~KoColorProfileStorage() (KoColorProfileStorage.cpp:56) ==6079== by 0x7AB8CE6: ~Private (KoColorSpaceRegistry.cpp:42) ==6079== by 0x7AB8CE6: KoColorSpaceRegistry::~KoColorSpaceRegistry() (KoColorSpaceRegistry.cpp:232) ==6079== by 0x7AB8F07: (anonymous namespace)::Q_QGS_s_instance::innerFunction()::Holder::~Holder() (KoColorSpaceRegistry.cpp:39) ==6079== by 0x70D7B5A: __run_exit_handlers (exit.c:89) ==6079== by 0x70D7CB0: exit (exit.c:143) ==6079== by 0x70BF2A0: (below main) (libc_start_call_main.h:74) ==6079== Block was alloc'd at ==6079== at 0x4840DDB: operator new(unsigned int) (vg_replace_malloc.c:415) ==6079== by 0x7AB9587: KoColorSpaceRegistry::init() (KoColorSpaceRegistry.cpp:164) ==6079== by 0x7ABA03B: KoColorSpaceRegistry::instance() (KoColorSpaceRegistry.cpp:141) ==6079== by 0x4ED0A94: KisApplication::loadPlugins() (KisApplication.cpp:386) ==6079== by 0x4ED3210: KisApplication::start(KisApplicationArguments const&) (KisApplication.cpp:459) ==6079== by 0x110793: main (main.cc:715) ==6079== And I really found the same pointer 0x557d2d4d7140 being added to the "duplicates" list here: Thread 1 hit Breakpoint 9, QList<KoColorProfile*>::append (this=this@entry=0x557d2d6870a0, t=@0x557d2d4d7298: 0x557d2d4d7140) at /usr/include/c++/12/bits/atomic_base.h:486 486 __glibcxx_assert(__b != memory_order_acq_rel); 1: x/i $pc => 0x7fd65c0afec0 <_ZN5QListIP14KoColorProfileE6appendERKS1_>: push %rbx (rr) bt #0 QList<KoColorProfile*>::append (this=this@entry=0x557d2d6870a0, t=@0x557d2d4d7298: 0x557d2d4d7140) at /usr/include/c++/12/bits/atomic_base.h:486 #1 0x00007fd65c0bd4e9 in KoColorProfileStorage::addProfile (this=0x557d2d563d68, profile=<optimized out>, profile@entry=0x557d2d541be0) at ./libs/pigment/KoColorProfileStorage.cpp:66 #2 0x00007fd65c0b014d in KoColorSpaceRegistry::addProfileToMap (this=this@entry=0x7fd65c3841f0 <(anonymous namespace)::Q_QGS_s_instance::innerFunction()::holder>, p=p@entry=0x557d2d541be0) at ./libs/pigment/KoColorSpaceRegistry.cpp:319 #3 0x00007fd637c7666e in LcmsEnginePlugin::LcmsEnginePlugin (this=0x557d2d51a0a0, parent=<optimized out>) at ./plugins/color/lcms2engine/LcmsEnginePlugin.cpp:138 #4 0x00007fd637c8e549 in KPluginFactory::createInstance<LcmsEnginePlugin, QObject> (parentWidget=<optimized out>, parent=<optimized out>, args=QList<QVariant> (size = 0)) at /usr/include/KF5/KCoreAddons/kpluginfactory.h:891 #5 0x00007fd65c729343 in KPluginFactory::create(char const*, QWidget*, QObject*, QList<QVariant> const&, QString const&) () from /lib/x86_64-linux-gnu/libKF5CoreAddons.so.5 #6 0x00007fd65c7880ed in KPluginFactory::create<QObject> (args=..., parent=<optimized out>, this=<optimized out>) at /usr/include/KF5/KCoreAddons/kpluginfactory.h:939 #7 KoPluginLoader::load (this=this@entry=0x7fd65c79c5c0 <(anonymous namespace)::Q_QGS_pluginLoaderInstance::innerFunction()::holder>, serviceType="Krita/ColorSpace", versionString="[X-Pigment-PluginVersion] == 28", config=..., owner=owner@entry=0x0, cache=cache@entry=true) at ./libs/koplugin/KoPluginLoader.cpp:128 #8 0x00007fd65c0b5f9d in KoColorSpaceRegistry::init (this=0x7fd65c3841f0 <(anonymous namespace)::Q_QGS_s_instance::innerFunction()::holder>) at ./libs/pigment/KoColorSpaceRegistry.cpp:187 #9 0x00007fd65c0b6592 in KoColorSpaceRegistry::instance () at ./libs/pigment/KoColorSpaceRegistry.cpp:39 #10 0x00007fd65f2b9123 in KisApplication::loadPlugins (this=<optimized out>) at ./libs/ui/KisApplication.cpp:386 #11 0x00007fd65f2bb8f6 in KisApplication::start (this=this@entry=0x7ffdc9b61f00, args=...) at ./libs/ui/KisApplication.cpp:459 #12 0x0000557d2c456e31 in main (argc=<optimized out>, argv=<optimized out>) at ./krita/main.cc:715 (rr) finish Run till exit from #0 QList<KoColorProfile*>::append (this=this@entry=0x557d2d6870a0, t=@0x557d2d4d7298: 0x557d2d4d7140) at /usr/include/c++/12/bits/atomic_base.h:486 KoColorProfileStorage::addProfile (this=0x557d2d563d68, profile=<optimized out>, profile@entry=0x557d2d541be0) at ./libs/pigment/KoColorProfileStorage.cpp:66 66 d->duplicates.append(d->profileUniqueIdMap[profile->uniqueId()]); 1: x/i $pc => 0x7fd65c0bd4e9 <_ZN21KoColorProfileStorage10addProfileEP14KoColorProfile+681>: mov 0x70(%rsp),%rdi (rr) print d->profileMap Could not find operator->. (rr) print d.d->profileMap $2 = QHash<QString, KoColorProfile *> (size = 10) = { ["scRGB (linear)"] = 0x557d2d7a8990, ["Artifex Software sGray ICC Profile"] = 0x557d2d7d4b60, ["Artifex Software sRGB ICC Profile"] = 0x557d2d53f9e0, ["Artifex CMYK SWOP Profile"] = 0x557d2d512a70, ["Artifex Software esRGB ICCProfile"] = 0x557d2d541b60, ["default"] = 0x557d2d4d7140, ["Chemical proof"] = 0x557d2d6fe5d0, ["High Dynamic Range UHDTV Wide Color Gamut Display (Rec. 2020) - SMPTE ST 2084 PQ EOTF"] = 0x557d2d783ab0, ["Artifex PS CMYK Profile"] = 0x557d2d541be0, ["Artifex Software A98 ICC Profile "] = 0x557d2dbc4f50 } (rr) print d.d->duplicates $3 = QList<KoColorProfile *> (size = 1) = { [0] = 0x557d2d4d7140 } Therefore it gets once freed in KoColorProfileStorage::Private::~Private the first loop over "profileMap". And then it crashes when it tries to free it a second time in the third loop over "duplicates". I assume this is related to this commit: https://invent.kde.org/graphics/krita/-/commit/ee16f1366178213cb0543003da86baab7b52fb65 Maybe removing in the first loop the deleted pointers also from the "duplicates" list could solve this issue? Like in following untested modification? --- krita-5.1.3+dfsg.orig/libs/pigment/KoColorProfileStorage.cpp +++ krita-5.1.3+dfsg/libs/pigment/KoColorProfileStorage.cpp @@ -31,10 +31,12 @@ struct KoColorProfileStorage::Private { { Q_FOREACH (KoColorProfile *p, profileMap) { profileUniqueIdMap.remove(p->uniqueId()); + duplicates.removeAll(p); delete p; } profileMap.clear(); Q_FOREACH (KoColorProfile *p, profileUniqueIdMap) { + duplicates.removeAll(p); delete p; } profileUniqueIdMap.clear(); Krita Version: 5.1.3 Hidpi: true Qt Version (compiled): 5.15.6 Version (loaded): 5.15.6 OS Information Build ABI: x86_64-little_endian-lp64 Build CPU: x86_64 CPU: x86_64 Kernel Type: linux Kernel Version: 6.0.0-5-amd64 Pretty Productname: Debian GNU/Linux bookworm/sid Product Type: debian Product Version: unknown Desktop: -- You are receiving this mail because: You are watching all bug changes.