From 0ea1af03a138cc8c6bc5dba3098be2151787016f Mon Sep 17 00:00:00 2001 From: reuk Date: Thu, 7 Nov 2024 16:22:22 +0000 Subject: [PATCH] ListenerList: Fix rare use-after-free when assertions are enabled This issue manifested on Linux when building in Debug mode. It may also have caused issues on other platforms. When editing a slider's value using its text box, and then pressing the enter key, the program would crash. The issue was not present when running with address sanitizer. Valgrind was able to find the problem. --- modules/juce_core/containers/juce_ListenerList.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/modules/juce_core/containers/juce_ListenerList.h b/modules/juce_core/containers/juce_ListenerList.h index 4856f321b06a..3b4b24956c66 100644 --- a/modules/juce_core/containers/juce_ListenerList.h +++ b/modules/juce_core/containers/juce_ListenerList.h @@ -230,7 +230,10 @@ class ListenerList Callback&& callback) { #if JUCE_ASSERTIONS_ENABLED_OR_LOGGED - const ScopedTryLock callCheckedExcludingLock (*callCheckedExcludingMutex); + // Keep a reference to the mutex to protect against the case where this list gets deleted + // during a callback. + auto localMutexPtr = callCheckedExcludingMutex; + const ScopedTryLock callCheckedExcludingLock (*localMutexPtr); // If you hit this assertion it means you're trying to call the listeners from multiple // threads concurrently. If you need to do this either use a LightweightListenerList, for a @@ -396,9 +399,9 @@ class ListenerList } #if JUCE_ASSERTIONS_ENABLED_OR_LOGGED - // using a unique_ptr helps keep the size of this class down to prevent excessive stack sizes + // using a shared_ptr helps keep the size of this class down to prevent excessive stack sizes // due to objects that contain a ListenerList being created on the stack - std::unique_ptr callCheckedExcludingMutex = std::make_unique(); + std::shared_ptr callCheckedExcludingMutex = std::make_shared(); #endif //==============================================================================