1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

Component: Avoid mouseListener use-after-free when deleting components in mouse callbacks

This commit is contained in:
reuk 2022-12-01 13:04:02 +00:00
parent a8162d124b
commit 2e16de3501
No known key found for this signature in database
GPG key ID: 9ADCD339CFC98A11

View file

@ -123,47 +123,32 @@ public:
template <typename EventMethod, typename... Params>
static void sendMouseEvent (HierarchyChecker& checker, EventMethod&& eventMethod, Params&&... params)
{
auto* parent = checker.nearestNonNullParent();
if (parent == nullptr)
return;
if (auto* list = parent->mouseListeners.get())
const auto callListeners = [&] (auto& parentComp, const auto findNumListeners)
{
for (int i = list->listeners.size(); --i >= 0;)
if (auto* list = parentComp.mouseListeners.get())
{
(list->listeners.getUnchecked (i)->*eventMethod) (checker.eventWithNearestParent(), params...);
const WeakReference safePointer { &parentComp };
if (checker.shouldBailOut())
return;
i = jmin (i, list->listeners.size());
}
}
for (Component* p = checker.nearestNonNullParent()->parentComponent; p != nullptr; p = p->parentComponent)
{
if (auto* list = p->mouseListeners.get())
{
if (list->numDeepMouseListeners > 0)
for (int i = findNumListeners (*list); --i >= 0; i = jmin (i, findNumListeners (*list)))
{
const auto shouldBailOut = [&checker, safePointer = WeakReference { p }]
{
return checker.shouldBailOut() || safePointer == nullptr;
};
(list->listeners.getUnchecked (i)->*eventMethod) (checker.eventWithNearestParent(), params...);
for (int i = list->numDeepMouseListeners; --i >= 0;)
{
(list->listeners.getUnchecked(i)->*eventMethod) (checker.eventWithNearestParent(), params...);
if (shouldBailOut())
return;
i = jmin (i, list->numDeepMouseListeners);
}
if (checker.shouldBailOut() || safePointer == nullptr)
return false;
}
}
}
return true;
};
if (auto* parent = checker.nearestNonNullParent())
if (! callListeners (*parent, [] (auto& list) { return list.listeners.size(); }))
return;
if (auto* parent = checker.nearestNonNullParent())
for (Component* p = parent->parentComponent; p != nullptr; p = p->parentComponent)
if (! callListeners (*p, [] (auto& list) { return list.numDeepMouseListeners; }))
return;
}
private: