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.

Reply via email to