From 0af182baa2f35d91b8dfaf0b5a8fef06b77dd03a Mon Sep 17 00:00:00 2001
From: Morph <39850852+Morph1984@users.noreply.github.com>
Date: Wed, 28 Apr 2021 11:32:44 -0400
Subject: [PATCH] applets/web: Fix a use-after-free when passing in the URL
 string

The URL string was being deleted before being used, leading to a use-after-free occurring when it is used afterwards.

Fix this by taking the string by const ref to extend its lifetime, ensuring it doesn't get deleted before use.
---
 src/core/frontend/applets/web_browser.cpp |  4 ++--
 src/core/frontend/applets/web_browser.h   |  9 +++++----
 src/yuzu/applets/web_browser.cpp          | 19 +++++++++----------
 src/yuzu/applets/web_browser.h            | 11 ++++++-----
 src/yuzu/main.cpp                         |  8 +++++---
 src/yuzu/main.h                           |  2 +-
 6 files changed, 28 insertions(+), 25 deletions(-)

diff --git a/src/core/frontend/applets/web_browser.cpp b/src/core/frontend/applets/web_browser.cpp
index 50db6a6542..be4736f473 100644
--- a/src/core/frontend/applets/web_browser.cpp
+++ b/src/core/frontend/applets/web_browser.cpp
@@ -12,7 +12,7 @@ WebBrowserApplet::~WebBrowserApplet() = default;
 DefaultWebBrowserApplet::~DefaultWebBrowserApplet() = default;
 
 void DefaultWebBrowserApplet::OpenLocalWebPage(
-    std::string_view local_url, std::function<void()> extract_romfs_callback,
+    const std::string& local_url, std::function<void()> extract_romfs_callback,
     std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback) const {
     LOG_WARNING(Service_AM, "(STUBBED) called, backend requested to open local web page at {}",
                 local_url);
@@ -21,7 +21,7 @@ void DefaultWebBrowserApplet::OpenLocalWebPage(
 }
 
 void DefaultWebBrowserApplet::OpenExternalWebPage(
-    std::string_view external_url,
+    const std::string& external_url,
     std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback) const {
     LOG_WARNING(Service_AM, "(STUBBED) called, backend requested to open external web page at {}",
                 external_url);
diff --git a/src/core/frontend/applets/web_browser.h b/src/core/frontend/applets/web_browser.h
index 1c5ef19a9b..d7bd44c277 100644
--- a/src/core/frontend/applets/web_browser.h
+++ b/src/core/frontend/applets/web_browser.h
@@ -16,11 +16,11 @@ public:
     virtual ~WebBrowserApplet();
 
     virtual void OpenLocalWebPage(
-        std::string_view local_url, std::function<void()> extract_romfs_callback,
+        const std::string& local_url, std::function<void()> extract_romfs_callback,
         std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback) const = 0;
 
     virtual void OpenExternalWebPage(
-        std::string_view external_url,
+        const std::string& external_url,
         std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback) const = 0;
 };
 
@@ -28,11 +28,12 @@ class DefaultWebBrowserApplet final : public WebBrowserApplet {
 public:
     ~DefaultWebBrowserApplet() override;
 
-    void OpenLocalWebPage(std::string_view local_url, std::function<void()> extract_romfs_callback,
+    void OpenLocalWebPage(const std::string& local_url,
+                          std::function<void()> extract_romfs_callback,
                           std::function<void(Service::AM::Applets::WebExitReason, std::string)>
                               callback) const override;
 
-    void OpenExternalWebPage(std::string_view external_url,
+    void OpenExternalWebPage(const std::string& external_url,
                              std::function<void(Service::AM::Applets::WebExitReason, std::string)>
                                  callback) const override;
 };
diff --git a/src/yuzu/applets/web_browser.cpp b/src/yuzu/applets/web_browser.cpp
index e482ba029e..93e3a4f6f2 100644
--- a/src/yuzu/applets/web_browser.cpp
+++ b/src/yuzu/applets/web_browser.cpp
@@ -102,8 +102,8 @@ QtNXWebEngineView::~QtNXWebEngineView() {
     StopInputThread();
 }
 
-void QtNXWebEngineView::LoadLocalWebPage(std::string_view main_url,
-                                         std::string_view additional_args) {
+void QtNXWebEngineView::LoadLocalWebPage(const std::string& main_url,
+                                         const std::string& additional_args) {
     is_local = true;
 
     LoadExtractedFonts();
@@ -113,12 +113,12 @@ void QtNXWebEngineView::LoadLocalWebPage(std::string_view main_url,
     SetLastURL("http://localhost/");
     StartInputThread();
 
-    load(QUrl(QUrl::fromLocalFile(QString::fromStdString(std::string(main_url))).toString() +
-              QString::fromStdString(std::string(additional_args))));
+    load(QUrl(QUrl::fromLocalFile(QString::fromStdString(main_url)).toString() +
+              QString::fromStdString(additional_args)));
 }
 
-void QtNXWebEngineView::LoadExternalWebPage(std::string_view main_url,
-                                            std::string_view additional_args) {
+void QtNXWebEngineView::LoadExternalWebPage(const std::string& main_url,
+                                            const std::string& additional_args) {
     is_local = false;
 
     SetUserAgent(UserAgent::WebApplet);
@@ -127,8 +127,7 @@ void QtNXWebEngineView::LoadExternalWebPage(std::string_view main_url,
     SetLastURL("http://localhost/");
     StartInputThread();
 
-    load(QUrl(QString::fromStdString(std::string(main_url)) +
-              QString::fromStdString(std::string(additional_args))));
+    load(QUrl(QString::fromStdString(main_url) + QString::fromStdString(additional_args)));
 }
 
 void QtNXWebEngineView::SetUserAgent(UserAgent user_agent) {
@@ -375,7 +374,7 @@ QtWebBrowser::QtWebBrowser(GMainWindow& main_window) {
 QtWebBrowser::~QtWebBrowser() = default;
 
 void QtWebBrowser::OpenLocalWebPage(
-    std::string_view local_url, std::function<void()> extract_romfs_callback_,
+    const std::string& local_url, std::function<void()> extract_romfs_callback_,
     std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback_) const {
     extract_romfs_callback = std::move(extract_romfs_callback_);
     callback = std::move(callback_);
@@ -390,7 +389,7 @@ void QtWebBrowser::OpenLocalWebPage(
 }
 
 void QtWebBrowser::OpenExternalWebPage(
-    std::string_view external_url,
+    const std::string& external_url,
     std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback_) const {
     callback = std::move(callback_);
 
diff --git a/src/yuzu/applets/web_browser.h b/src/yuzu/applets/web_browser.h
index 47f960d695..7ad07409f4 100644
--- a/src/yuzu/applets/web_browser.h
+++ b/src/yuzu/applets/web_browser.h
@@ -58,7 +58,7 @@ public:
      * @param main_url The url to the file.
      * @param additional_args Additional arguments appended to the main url.
      */
-    void LoadLocalWebPage(std::string_view main_url, std::string_view additional_args);
+    void LoadLocalWebPage(const std::string& main_url, const std::string& additional_args);
 
     /**
      * Loads an external website. Cannot be used to load local urls.
@@ -66,7 +66,7 @@ public:
      * @param main_url The url to the website.
      * @param additional_args Additional arguments appended to the main url.
      */
-    void LoadExternalWebPage(std::string_view main_url, std::string_view additional_args);
+    void LoadExternalWebPage(const std::string& main_url, const std::string& additional_args);
 
     /**
      * Sets the background color of the web page.
@@ -193,16 +193,17 @@ public:
     explicit QtWebBrowser(GMainWindow& parent);
     ~QtWebBrowser() override;
 
-    void OpenLocalWebPage(std::string_view local_url, std::function<void()> extract_romfs_callback_,
+    void OpenLocalWebPage(const std::string& local_url,
+                          std::function<void()> extract_romfs_callback_,
                           std::function<void(Service::AM::Applets::WebExitReason, std::string)>
                               callback_) const override;
 
-    void OpenExternalWebPage(std::string_view external_url,
+    void OpenExternalWebPage(const std::string& external_url,
                              std::function<void(Service::AM::Applets::WebExitReason, std::string)>
                                  callback_) const override;
 
 signals:
-    void MainWindowOpenWebPage(std::string_view main_url, std::string_view additional_args,
+    void MainWindowOpenWebPage(const std::string& main_url, const std::string& additional_args,
                                bool is_local) const;
 
 private:
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 5f6cdc0c6f..2fd38a851e 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -574,8 +574,8 @@ void GMainWindow::SoftwareKeyboardExit() {
     software_keyboard = nullptr;
 }
 
-void GMainWindow::WebBrowserOpenWebPage(std::string_view main_url, std::string_view additional_args,
-                                        bool is_local) {
+void GMainWindow::WebBrowserOpenWebPage(const std::string& main_url,
+                                        const std::string& additional_args, bool is_local) {
 #ifdef YUZU_USE_QT_WEB_ENGINE
 
     if (disable_web_applet) {
@@ -596,13 +596,15 @@ void GMainWindow::WebBrowserOpenWebPage(std::string_view main_url, std::string_v
         loading_progress.setRange(0, 3);
         loading_progress.setValue(0);
 
-        if (is_local && !Common::FS::Exists(std::string(main_url))) {
+        if (is_local && !Common::FS::Exists(main_url)) {
             loading_progress.show();
 
             auto future = QtConcurrent::run([this] { emit WebBrowserExtractOfflineRomFS(); });
 
             while (!future.isFinished()) {
                 QCoreApplication::processEvents();
+
+                std::this_thread::sleep_for(std::chrono::milliseconds(1));
             }
         }
 
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index 7f1e50a5b0..98a608fce3 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -159,7 +159,7 @@ public slots:
     void SoftwareKeyboardExit();
     void ErrorDisplayDisplayError(QString error_code, QString error_text);
     void ProfileSelectorSelectProfile();
-    void WebBrowserOpenWebPage(std::string_view main_url, std::string_view additional_args,
+    void WebBrowserOpenWebPage(const std::string& main_url, const std::string& additional_args,
                                bool is_local);
     void OnAppFocusStateChanged(Qt::ApplicationState state);