From 91e1ae23e893fbe12b3334b6b923114966807cb1 Mon Sep 17 00:00:00 2001 From: Jens Stutte Date: Wed, 9 Feb 2022 09:01:45 +0000 Subject: [PATCH] Bug 1752863: Prevent recursion while xhr.send is running. r=dom-worker-reviewers,asuth Differential Revision: https://phabricator.services.mozilla.com/D138131 --- dom/xhr/XMLHttpRequestWorker.cpp | 12 ++++++++++ dom/xhr/XMLHttpRequestWorker.h | 1 + dom/xhr/tests/mochitest.ini | 2 ++ dom/xhr/tests/test_bug1752863.html | 29 +++++++++++++++++++++++++ dom/xhr/tests/test_bug1752863_worker.js | 29 +++++++++++++++++++++++++ 5 files changed, 73 insertions(+) create mode 100644 dom/xhr/tests/test_bug1752863.html create mode 100644 dom/xhr/tests/test_bug1752863_worker.js diff --git a/dom/xhr/XMLHttpRequestWorker.cpp b/dom/xhr/XMLHttpRequestWorker.cpp index 4453108857e7..9f98a2c2c915 100644 --- a/dom/xhr/XMLHttpRequestWorker.cpp +++ b/dom/xhr/XMLHttpRequestWorker.cpp @@ -1355,6 +1355,7 @@ XMLHttpRequestWorker::XMLHttpRequestWorker(WorkerPrivate* aWorkerPrivate, mBackgroundRequest(false), mWithCredentials(false), mCanceled(false), + mFlagSendActive(false), mMozAnon(false), mMozSystem(false), mMimeTypeOverride(VoidString()) { @@ -1881,6 +1882,17 @@ void XMLHttpRequestWorker::Send( ErrorResult& aRv) { mWorkerPrivate->AssertIsOnWorkerThread(); + if (mFlagSendActive) { + aRv.Throw(NS_ERROR_DOM_INVALID_STATE_XHR_HAS_INVALID_CONTEXT); + return; + } + mFlagSendActive = true; + auto clearRecursionFlag = MakeScopeExit([&]() { + // No one else should have touched this flag. + MOZ_ASSERT(mFlagSendActive); + mFlagSendActive = false; + }); + if (mCanceled) { aRv.ThrowUncatchableException(); return; diff --git a/dom/xhr/XMLHttpRequestWorker.h b/dom/xhr/XMLHttpRequestWorker.h index c1aa6cc16b81..4583f27a01b1 100644 --- a/dom/xhr/XMLHttpRequestWorker.h +++ b/dom/xhr/XMLHttpRequestWorker.h @@ -77,6 +77,7 @@ class XMLHttpRequestWorker final : public XMLHttpRequest { bool mBackgroundRequest; bool mWithCredentials; bool mCanceled; + bool mFlagSendActive; bool mMozAnon; bool mMozSystem; diff --git a/dom/xhr/tests/mochitest.ini b/dom/xhr/tests/mochitest.ini index 90d5f62c7085..b2e8ba29c298 100644 --- a/dom/xhr/tests/mochitest.ini +++ b/dom/xhr/tests/mochitest.ini @@ -129,3 +129,5 @@ support-files = xhr_worker_doubleSend.js support-files = xhr_sharedworker.js [test_bug1697539.html] support-files = worker_bug1697539.js +[test_bug1752863.html] +support-files = test_bug1752863_worker.js diff --git a/dom/xhr/tests/test_bug1752863.html b/dom/xhr/tests/test_bug1752863.html new file mode 100644 index 000000000000..5cf67d9396a3 --- /dev/null +++ b/dom/xhr/tests/test_bug1752863.html @@ -0,0 +1,29 @@ + + + + + Test for Bug 1752863 + + + + + diff --git a/dom/xhr/tests/test_bug1752863_worker.js b/dom/xhr/tests/test_bug1752863_worker.js new file mode 100644 index 000000000000..d7ee65ad662e --- /dev/null +++ b/dom/xhr/tests/test_bug1752863_worker.js @@ -0,0 +1,29 @@ +self.onmessage = async function(ev) { + var xhr = new XMLHttpRequest({ mozAnon: false }); + var myself = self; + xhr.addEventListener( + "loadstart", + async () => { + try { + xhr.open("POST", "FOOBAR", false); + xhr.send(); + // We do not expect to ever get here. However, this would happen + // if the loadstart event would be queued and not directly + // executed on the same C++ stack of the xhr.send syncloop. + myself.postMessage("MissingError"); + } catch (err) { + if (err instanceof DOMException) { + // This is what we expect to happen. + myself.postMessage("DOMException"); + } else { + myself.postMessage("OtherError"); + } + } + }, + true + ); + xhr.open("POST", "FOOBAR", false); + xhr.send(); + // We do not expect to ever get here, see "MissingError". + postMessage("TERMINATE"); +};