From 1cf2bfc2c871117c6cdad044e4d8bd3c22235ad3 Mon Sep 17 00:00:00 2001 From: David Li Date: Fri, 6 Jan 2023 09:02:33 -0800 Subject: [PATCH] Cherry-pick 252432.1019@safari-7614-branch (1988807a5229). rdar://103307563 [Clipboard] Explicitly call completion on clearing ClipboardItemTypeLoader rdar://103307563 Reviewed by Jonathan Bedard and Wenson Hsieh. In m_itemTypeLoaders.clear(), ClipboardItemBindingsDataSource::invokeCompletionHandler() is called after all m_itemTypeLoaders released and traverses the itemTypeLoaders after itemTypeLoaders is clear but before the size is updated, causing nullptr accessment. So we should explicitly call completion before itemTypeLoader is released. * LayoutTests/editing/async-clipboard/clipboard-clear-expected.txt: Added. * LayoutTests/editing/async-clipboard/clipboard-clear.html: Added. * Source/WebCore/Modules/async-clipboard/ClipboardItemBindingsDataSource.cpp: (WebCore::ClipboardItemBindingsDataSource::clearItemTypeLoaders): (WebCore::ClipboardItemBindingsDataSource::collectDataForWriting): (WebCore::ClipboardItemBindingsDataSource::ClipboardItemTypeLoader::~ClipboardItemTypeLoader): * Source/WebCore/Modules/async-clipboard/ClipboardItemBindingsDataSource.h: Canonical link: https://commits.webkit.org/252432.1019@safari-7614-branch --- .../clipboard-clear-expected.txt | 1 + .../async-clipboard/clipboard-clear.html | 27 +++++++++++++++++++ .../ClipboardItemBindingsDataSource.cpp | 14 +++++++--- .../ClipboardItemBindingsDataSource.h | 4 ++- 4 files changed, 42 insertions(+), 4 deletions(-) create mode 100644 LayoutTests/editing/async-clipboard/clipboard-clear-expected.txt create mode 100644 LayoutTests/editing/async-clipboard/clipboard-clear.html diff --git a/LayoutTests/editing/async-clipboard/clipboard-clear-expected.txt b/LayoutTests/editing/async-clipboard/clipboard-clear-expected.txt new file mode 100644 index 000000000000..c2541f4f3dd7 --- /dev/null +++ b/LayoutTests/editing/async-clipboard/clipboard-clear-expected.txt @@ -0,0 +1 @@ +PASS if no crash. diff --git a/LayoutTests/editing/async-clipboard/clipboard-clear.html b/LayoutTests/editing/async-clipboard/clipboard-clear.html new file mode 100644 index 000000000000..1c5b321e21bc --- /dev/null +++ b/LayoutTests/editing/async-clipboard/clipboard-clear.html @@ -0,0 +1,27 @@ + + + + + + +

PASS if no crash.

+ + diff --git a/Source/WebCore/Modules/async-clipboard/ClipboardItemBindingsDataSource.cpp b/Source/WebCore/Modules/async-clipboard/ClipboardItemBindingsDataSource.cpp index ad404d7f2928..39dd80f4b067 100644 --- a/Source/WebCore/Modules/async-clipboard/ClipboardItemBindingsDataSource.cpp +++ b/Source/WebCore/Modules/async-clipboard/ClipboardItemBindingsDataSource.cpp @@ -123,9 +123,17 @@ void ClipboardItemBindingsDataSource::getType(const String& type, Ref)>&& completion) +void ClipboardItemBindingsDataSource::clearItemTypeLoaders() { + for (auto& itemTypeLoader : m_itemTypeLoaders) + itemTypeLoader->invokeCompletionHandler(); + m_itemTypeLoaders.clear(); +} + +void ClipboardItemBindingsDataSource::collectDataForWriting(Clipboard& destination, CompletionHandler)>&& completion) +{ + clearItemTypeLoaders(); ASSERT(!m_completionHandler); m_completionHandler = WTFMove(completion); m_writingDestination = destination; @@ -238,8 +246,8 @@ ClipboardItemBindingsDataSource::ClipboardItemTypeLoader::~ClipboardItemTypeLoad { if (m_blobLoader) m_blobLoader->cancel(); - - invokeCompletionHandler(); + + ASSERT(!m_completionHandler); } void ClipboardItemBindingsDataSource::ClipboardItemTypeLoader::didFinishLoading() diff --git a/Source/WebCore/Modules/async-clipboard/ClipboardItemBindingsDataSource.h b/Source/WebCore/Modules/async-clipboard/ClipboardItemBindingsDataSource.h index ad4d36b07ff4..c3395c59b554 100644 --- a/Source/WebCore/Modules/async-clipboard/ClipboardItemBindingsDataSource.h +++ b/Source/WebCore/Modules/async-clipboard/ClipboardItemBindingsDataSource.h @@ -51,6 +51,7 @@ class ClipboardItemBindingsDataSource : public ClipboardItemDataSource { void getType(const String&, Ref&&) final; void collectDataForWriting(Clipboard& destination, CompletionHandler)>&&) final; + void clearItemTypeLoaders(); void invokeCompletionHandler(); using BufferOrString = std::variant>; @@ -67,6 +68,8 @@ class ClipboardItemBindingsDataSource : public ClipboardItemDataSource { void didFailToResolve(); void didResolveToBlob(ScriptExecutionContext&, Ref&&); + void invokeCompletionHandler(); + const String& type() { return m_type; } const BufferOrString& data() { return m_data; } @@ -74,7 +77,6 @@ class ClipboardItemBindingsDataSource : public ClipboardItemDataSource { ClipboardItemTypeLoader(const String& type, CompletionHandler&&); void sanitizeDataIfNeeded(); - void invokeCompletionHandler(); // FileReaderLoaderClient methods. void didStartLoading() final { }