Commit fa04bf7f authored by Milian Wolff's avatar Milian Wolff
Browse files

DUChain: call delete on correct type

Because the DUChainBaseData doesn't have a vtable yet is used
polymorphically in the DUChain, we have to make sure to call
delete on the correct type.

Generally, instead of manually calling the destructor of the
concrete type and then deleting the base type, we should just
call delete on the concrete type directly.

Fixes ASAN report:
```
==72034==ERROR: AddressSanitizer: new-delete-type-mismatch on 0x606000359de0 in thread T0:
  object passed to delete has wrong type:
  size of the allocated type:   56 bytes;
  size of the deallocated type: 20 bytes.
    #0 0x7f0393be7009 in operator delete(void*, unsigned long) /build/gcc/src/gcc/libsanitizer/asan/asan_new_delete.cpp:172
    #1 0x7f038a46985d in KDevelop::DUChainBase::~DUChainBase() /home/milian/projects/kf5/src/extragear/kdevelop/kdevelop/kdevplatform/language/duchain/duchainbase.cpp:98
    #2 0x7f038a10b691 in KDevelop::DUContext::~DUContext() /home/milian/projects/kf5/src/extragear/kdevelop/kdevelop/kdevplatform/language/duchain/ducontext.cpp:431
    #3 0x7f038a10c68e in KDevelop::DUContext::~DUContext() /home/milian/projects/kf5/src/extragear/kdevelop/kdevelop/kdevplatform/language/duchain/ducontext.cpp:477
    #4 0x7f038a13855b in void qDeleteAll<QTypedArrayData<KDevelop::DUContext*>::const_iterator>(QTypedArrayData<KDevelop::DUContext*>::const_iterator, QTypedArrayData<KDevelop::DUContext*>::const_iterator) /usr/include/qt/QtCore/qalgorithms.h:320
    #5 0x7f038a0a5d0f in void qDeleteAll<QVector<KDevelop::DUContext*> >(QVector<KDevelop::DUContext*> const&) /usr/include/qt/QtCore/qalgorithms.h:328
    #6 0x7f038a0a5d0f in KDevelop::DUContext::deleteChildContextsRecursively() /home/milian/projects/kf5/src/extragear/kdevelop/kdevelop/kdevplatform/language/duchain/ducontext.cpp:1067
    #7 0x7f038a20094c in KDevelop::TopDUContext::~TopDUContext() /home/milian/projects/kf5/src/extragear/kdevelop/kdevelop/kdevplatform/language/duchain/topducontext.cpp:586
    #8 0x7f038a200f72 in KDevelop::TopDUContext::~TopDUContext() /home/milian/projects/kf5/src/extragear/kdevelop/kdevelop/kdevplatform/language/duchain/topducontext.cpp:589
    #9 0x7f038a1f3b23 in KDevelop::TopDUContext::deleteSelf() /home/milian/projects/kf5/src/extragear/kdevelop/kdevelop/kdevplatform/language/duchain/topducontext.cpp:599
    #10 0x7f038a0626b5 in KDevelop::DUChainPrivate::removeDocumentChainFromMemory(KDevelop::TopDUContext*) /home/milian/projects/kf5/src/extragear/kdevelop/kdevelop/kdevplatform/language/duchain/duchain.cpp:456
    #11 0x7f0389f49264 in KDevelop::DUChain::removeDocumentChain(KDevelop::TopDUContext*) /home/milian/projects/kf5/src/extragear/kdevelop/kdevelop/kdevplatform/language/duchain/duchain.cpp:1312
    #12 0x55ea5065b6fa in TestContext::~TestContext() /home/milian/projects/kf5/src/extragear/kdevelop/kdevelop/kdevplatform/language/duchain/tests/test_duchain.cpp:454
    #13 0x55ea505e5462 in TestDUChain::testImportStructure() /home/milian/projects/kf5/src/extragear/kdevelop/kdevelop/kdevplatform/language/duchain/tests/test_duchain.cpp:651

0x606000359de0 is located 0 bytes inside of 56-byte region [0x606000359de0,0x606000359e18)
allocated by thread T0 here:
    #0 0x7f0393be5f41 in operator new(unsigned long) /build/gcc/src/gcc/libsanitizer/asan/asan_new_delete.cpp:99
    #1 0x7f038a0dedb1 in KDevelop::DUContext::DUContext(KDevelop::RangeInRevision const&, KDevelop::DUContext*, bool) /home/milian/projects/kf5/src/extragear/kdevelop/kdevelop/kdevplatform/language/duchain/ducontext.cpp:357
```
parent 1983ec2b
......@@ -79,11 +79,14 @@ void DUChainBase::setData(DUChainBaseData* data, bool constructorCalled)
Q_ASSERT(data);
Q_ASSERT(d_ptr);
if (constructorCalled)
if (d_ptr->m_dynamic) {
Q_ASSERT(constructorCalled);
DUChainItemSystem::self().deleteDynamicData(d_ptr);
} else if (constructorCalled) {
// If the data object isn't dynamic, then it is part of a central repository, and cannot be deleted here.
// we still need to call the destructor though
KDevelop::DUChainItemSystem::self().callDestructor(static_cast<DUChainBaseData*>(d_ptr));
if (d_ptr->m_dynamic) // If the data object isn't dynamic, then it is part of a central repository, and cannot be deleted here.
delete d_ptr;
}
d_ptr = data;
}
......@@ -94,8 +97,7 @@ DUChainBase::~DUChainBase()
m_ptr->m_base = nullptr;
if (d_ptr->m_dynamic) {
KDevelop::DUChainItemSystem::self().callDestructor(d_ptr);
delete d_ptr;
DUChainItemSystem::self().deleteDynamicData(d_ptr);
d_ptr = nullptr;
}
}
......
......@@ -60,6 +60,13 @@ void DUChainItemSystem::freeDynamicData(KDevelop::DUChainBaseData* data) const
m_factories[data->classId]->freeDynamicData(data);
}
void DUChainItemSystem::deleteDynamicData(DUChainBaseData* data) const
{
if (uint(m_factories.size()) <= data->classId || m_factories[data->classId] == nullptr)
return;
m_factories[data->classId]->deleteDynamicData(data);
}
uint DUChainItemSystem::dynamicSize(const DUChainBaseData& data) const
{
if (uint(m_factories.size()) <= data.classId || m_factories[data.classId] == nullptr)
......
......@@ -34,6 +34,7 @@ public:
virtual DUChainBase* create(DUChainBaseData* data) const = 0;
virtual void callDestructor(DUChainBaseData* data) const = 0;
virtual void freeDynamicData(DUChainBaseData* data) const = 0;
virtual void deleteDynamicData(DUChainBaseData* data) const = 0;
virtual void copy(const DUChainBaseData& from, DUChainBaseData& to, bool constant) const = 0;
virtual DUChainBaseData* cloneData(const DUChainBaseData& data) const = 0;
virtual uint dynamicSize(const DUChainBaseData& data) const = 0;
......@@ -83,6 +84,12 @@ public:
static_cast<Data*>(data)->freeDynamicData();
}
void deleteDynamicData(DUChainBaseData* data) const override
{
Q_ASSERT(data->classId == T::Identity);
delete static_cast<Data*>(data);
}
uint dynamicSize(const DUChainBaseData& data) const override
{
Q_ASSERT(data.classId == T::Identity);
......@@ -164,6 +171,9 @@ public:
///This needs to be called whenever a dynamic duchain data-pointer is being deleted.
void freeDynamicData(DUChainBaseData* data) const;
/// Call delete on @p data
void deleteDynamicData(DUChainBaseData* data) const;
/// Access the static DUChainItemSystem instance.
static DUChainItemSystem& self();
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment