From b4ce08318537bf02b37fd115e1b01e043a253f7d Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Wed, 1 Jul 2020 18:16:39 -0400 Subject: [PATCH] Prevent possible dangling pointers to Project from Clipboard --- src/Clipboard.cpp | 4 ++-- src/Clipboard.h | 6 +++--- src/Project.h | 1 + src/menus/EditMenus.cpp | 14 ++++++++------ src/menus/LabelMenus.cpp | 3 ++- 5 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/Clipboard.cpp b/src/Clipboard.cpp index 5c5d23fd4..58b45a3d8 100644 --- a/src/Clipboard.cpp +++ b/src/Clipboard.cpp @@ -34,7 +34,7 @@ void Clipboard::Clear() { mT0 = 0.0; mT1 = 0.0; - mProject = nullptr; + mProject.reset(); mTracks->Clear(); // Emit an event for listeners @@ -42,7 +42,7 @@ void Clipboard::Clear() } void Clipboard::Assign( TrackList && newContents, - double t0, double t1, AudacityProject *pProject ) + double t0, double t1, const std::weak_ptr &pProject ) { newContents.Swap( *mTracks ); newContents.Clear(); diff --git a/src/Clipboard.h b/src/Clipboard.h index ead19df76..43dffb0f7 100644 --- a/src/Clipboard.h +++ b/src/Clipboard.h @@ -35,20 +35,20 @@ public: double T1() const { return mT1; } double Duration() const { return mT1 - mT0; } - AudacityProject *Project() const { return mProject; } + const std::weak_ptr &Project() const { return mProject; } void Clear(); void Assign( TrackList && newContents, double t0, double t1, - AudacityProject *pProject ); + const std::weak_ptr &pProject ); private: Clipboard(); ~Clipboard(); std::shared_ptr mTracks; - AudacityProject *mProject{}; + std::weak_ptr mProject{}; double mT0{ 0 }; double mT1{ 0 }; }; diff --git a/src/Project.h b/src/Project.h index b3a34f274..047858fa2 100644 --- a/src/Project.h +++ b/src/Project.h @@ -103,6 +103,7 @@ class AUDACITY_DLL_API AudacityProject final : public wxEvtHandler , public AttachedObjects , public AttachedWindows + , public std::enable_shared_from_this { public: using AttachedObjects = ::AttachedObjects; diff --git a/src/menus/EditMenus.cpp b/src/menus/EditMenus.cpp index 3c96ef36a..f28284c98 100644 --- a/src/menus/EditMenus.cpp +++ b/src/menus/EditMenus.cpp @@ -85,6 +85,7 @@ bool DoPasteNothingSelected(AudacityProject &project) else { const auto &clipboard = Clipboard::Get(); + auto clipboardProject = clipboard.Project().lock(); auto clipTrackRange = clipboard.GetTracks().Any< const Track >(); if (clipTrackRange.empty()) return true; // nothing to paste @@ -97,7 +98,7 @@ bool DoPasteNothingSelected(AudacityProject &project) Track *pNewTrack; pClip->TypeSwitch( [&](const WaveTrack *wc) { - if ((clipboard.Project() != &project)) + if ((clipboardProject.get() != &project)) // Cause duplication of block files on disk, when copy is // between projects locker.emplace(wc); @@ -277,7 +278,7 @@ void OnCut(const CommandContext &context) std::move( newClipboard ), selectedRegion.t0(), selectedRegion.t1(), - &project + project.shared_from_this() ); // Proceed to change the project. If this throws, the project will be @@ -369,7 +370,7 @@ void OnCopy(const CommandContext &context) // Survived possibility of exceptions. Commit changes to the clipboard now. clipboard.Assign( std::move( newClipboard ), - selectedRegion.t0(), selectedRegion.t1(), &project ); + selectedRegion.t0(), selectedRegion.t1(), project.shared_from_this() ); //Make sure the menus/toolbar states get updated trackPanel.Refresh(false); @@ -415,6 +416,7 @@ void OnPaste(const CommandContext &context) auto pC = clipTrackRange.begin(); size_t nnChannels=0, ncChannels=0; + auto clipboardProject = clipboard.Project().lock(); while (*pN && *pC) { auto n = *pN; auto c = *pC; @@ -507,7 +509,7 @@ void OnPaste(const CommandContext &context) n->TypeSwitch( [&](WaveTrack *wn){ const auto wc = static_cast(c); - if (clipboard.Project() != &project) + if (clipboardProject.get() != &project) // Cause duplication of block files on disk, when copy is // between projects locker.emplace(wc); @@ -581,7 +583,7 @@ void OnPaste(const CommandContext &context) const auto wc = *clipboard.GetTracks().Any< const WaveTrack >().rbegin(); Optional locker; - if (clipboard.Project() != &project && wc) + if (clipboardProject.get() != &project && wc) // Cause duplication of block files on disk, when copy is // between projects locker.emplace(static_cast(wc)); @@ -702,7 +704,7 @@ void OnSplitCut(const CommandContext &context) // Survived possibility of exceptions. Commit changes to the clipboard now. clipboard.Assign( std::move( newClipboard ), - selectedRegion.t0(), selectedRegion.t1(), &project ); + selectedRegion.t0(), selectedRegion.t1(), project.shared_from_this() ); ProjectHistory::Get( project ) .PushState(XO("Split-cut to the clipboard"), XO("Split Cut")); diff --git a/src/menus/LabelMenus.cpp b/src/menus/LabelMenus.cpp index 21c51f436..a77ad165c 100644 --- a/src/menus/LabelMenus.cpp +++ b/src/menus/LabelMenus.cpp @@ -4,6 +4,7 @@ #include "../LabelTrack.h" #include "../Menus.h" #include "../Prefs.h" +#include "../Project.h" #include "../ProjectAudioIO.h" #include "../ProjectHistory.h" #include "../ProjectWindow.h" @@ -266,7 +267,7 @@ void EditClipboardByLabel( AudacityProject &project, // Survived possibility of exceptions. Commit changes to the clipboard now. clipboard.Assign( std::move( newClipboard ), - regions.front().start, regions.back().end, &project ); + regions.front().start, regions.back().end, project.shared_from_this() ); } }