From 548fbd814bdd77c8e537adf8745e5168533871c2 Mon Sep 17 00:00:00 2001
From: Thomas Goyne <plorkyeran@aegisub.org>
Date: Thu, 10 Jul 2014 19:57:19 -0700
Subject: [PATCH] Fix a use-after-free when a SubsEditCtrl is destroyed while
 the thesaurus is loading

---
 src/thesaurus.cpp | 13 ++++++++++---
 src/thesaurus.h   |  3 +++
 2 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/src/thesaurus.cpp b/src/thesaurus.cpp
index 7f0b396f5..025110a08 100644
--- a/src/thesaurus.cpp
+++ b/src/thesaurus.cpp
@@ -42,7 +42,7 @@ Thesaurus::Thesaurus()
 }
 
 Thesaurus::~Thesaurus() {
-	// Explicit empty destructor needed for scoped_ptr with incomplete types
+	if (cancel_load) *cancel_load = true;
 }
 
 std::vector<Thesaurus::Entry> Thesaurus::Lookup(std::string word) {
@@ -98,11 +98,18 @@ void Thesaurus::OnLanguageChanged() {
 
 	LOG_I("thesaurus/file") << "Using thesaurus: " << dat;
 
+	if (cancel_load) *cancel_load = true;
+	cancel_load = new bool{false};
+	auto cancel = cancel_load; // Needed to avoid capturing via `this`
 	agi::dispatch::Background().Async([=]{
 		try {
 			auto thes = agi::make_unique<agi::Thesaurus>(dat, idx);
-			agi::dispatch::Main().Sync([&thes, this]{
-				impl = std::move(thes);
+			agi::dispatch::Main().Sync([&thes, cancel, this]{
+				if (!*cancel) {
+					impl = std::move(thes);
+					cancel_load = nullptr;
+				}
+				delete cancel;
 			});
 		}
 		catch (agi::Exception const& e) {
diff --git a/src/thesaurus.h b/src/thesaurus.h
index 0383cce45..662dbb76b 100644
--- a/src/thesaurus.h
+++ b/src/thesaurus.h
@@ -39,6 +39,9 @@ class Thesaurus {
 	agi::signal::Connection dict_path_listener;
 	/// Thesaurus path change handler
 	void OnPathChanged();
+
+	bool *cancel_load = nullptr;
+
 public:
 	/// A pair of a word and synonyms for that word
 	typedef std::pair<std::string, std::vector<std::string>> Entry;
-- 
GitLab