From 6473deb155f147401a328a99594e6ce40b21edd4 Mon Sep 17 00:00:00 2001 From: reuk Date: Wed, 27 Aug 2025 15:24:48 +0100 Subject: [PATCH] PluginListComponent: Fix potential use-after-free on modal component dismiss --- .../scanning/juce_PluginListComponent.cpp | 19 +++++++++++++------ .../scanning/juce_PluginListComponent.h | 2 +- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/modules/juce_audio_processors/scanning/juce_PluginListComponent.cpp b/modules/juce_audio_processors/scanning/juce_PluginListComponent.cpp index f51c8b50d0..d8b9ff76e0 100644 --- a/modules/juce_audio_processors/scanning/juce_PluginListComponent.cpp +++ b/modules/juce_audio_processors/scanning/juce_PluginListComponent.cpp @@ -154,7 +154,8 @@ public: }; //============================================================================== -class PluginListComponent::Scanner final : private Timer +class PluginListComponent::Scanner final : public std::enable_shared_from_this, + private Timer { public: Scanner (PluginListComponent& plc, AudioPluginFormat& format, const StringArray& filesOrIdentifiers, @@ -321,9 +322,10 @@ private: progressWindow.addButton (TRANS ("Cancel"), 0, KeyPress (KeyPress::escapeKey)); progressWindow.addProgressBarComponent (progress); - progressWindow.enterModalState (true, ModalCallbackFunction::create ([this] (auto) + progressWindow.enterModalState (true, ModalCallbackFunction::create ([weak = weak_from_this()] (auto) { - flags |= stopRequested; + if (const auto strong = weak.lock()) + strong->flags |= stopRequested; })); if (numThreads > 0) @@ -650,9 +652,14 @@ void PluginListComponent::scanFor (AudioPluginFormat& format) void PluginListComponent::scanFor (AudioPluginFormat& format, const StringArray& filesOrIdentifiersToScan) { - currentScanner.reset (new Scanner (*this, format, filesOrIdentifiersToScan, propertiesToUse, allowAsync, numThreads, - dialogTitle.isNotEmpty() ? dialogTitle : TRANS ("Scanning for plug-ins..."), - dialogText.isNotEmpty() ? dialogText : TRANS ("Searching for all possible plug-in files..."))); + currentScanner = std::make_shared (*this, + format, + filesOrIdentifiersToScan, + propertiesToUse, + allowAsync, + numThreads, + dialogTitle.isNotEmpty() ? dialogTitle : TRANS ("Scanning for plug-ins..."), + dialogText.isNotEmpty() ? dialogText : TRANS ("Searching for all possible plug-in files...")); } bool PluginListComponent::isScanning() const noexcept diff --git a/modules/juce_audio_processors/scanning/juce_PluginListComponent.h b/modules/juce_audio_processors/scanning/juce_PluginListComponent.h index 2cb7798a9b..a65ba1237f 100644 --- a/modules/juce_audio_processors/scanning/juce_PluginListComponent.h +++ b/modules/juce_audio_processors/scanning/juce_PluginListComponent.h @@ -137,7 +137,7 @@ private: std::unique_ptr tableModel; class Scanner; - std::unique_ptr currentScanner; + std::shared_ptr currentScanner; ScopedMessageBox messageBox;