232 lines
7.0 KiB
Diff
232 lines
7.0 KiB
Diff
From 309ddf3970408bb3cf21a2eeee31104452bddc67 Mon Sep 17 00:00:00 2001
|
|
From: Peter Van der Beken <peterv@propagandism.org>
|
|
Date: Tue, 21 Dec 2021 17:56:02 +0000 (2021-12-22)
|
|
Subject: [PATCH] CVE-2022-22755
|
|
|
|
---
|
|
dom/xslt/xslt/txExecutionState.cpp | 7 +-
|
|
dom/xslt/xslt/txExecutionState.h | 5 +-
|
|
dom/xslt/xslt/txMozillaXSLTProcessor.cpp | 101 ++++++++++++++++++++++-
|
|
dom/xslt/xslt/txXSLTProcessor.cpp | 25 ++++--
|
|
4 files changed, 126 insertions(+), 12 deletions(-)
|
|
|
|
diff --git a/dom/xslt/xslt/txExecutionState.cpp b/dom/xslt/xslt/txExecutionState.cpp
|
|
index a4e7609dfc..8d849886ac 100644
|
|
--- a/dom/xslt/xslt/txExecutionState.cpp
|
|
+++ b/dom/xslt/xslt/txExecutionState.cpp
|
|
@@ -417,7 +417,12 @@ txExecutionState::TemplateRule* txExecutionState::getCurrentTemplateRule() {
|
|
return &mTemplateRules[mTemplateRules.Length() - 1];
|
|
}
|
|
|
|
-txInstruction* txExecutionState::getNextInstruction() {
|
|
+mozilla::Result<txInstruction*, nsresult>
|
|
+txExecutionState::getNextInstruction() {
|
|
+ if (mStopProcessing) {
|
|
+ return mozilla::Err(NS_ERROR_FAILURE);
|
|
+ }
|
|
+
|
|
txInstruction* instr = mNextInstruction;
|
|
if (instr) {
|
|
mNextInstruction = instr->mNext.get();
|
|
diff --git a/dom/xslt/xslt/txExecutionState.h b/dom/xslt/xslt/txExecutionState.h
|
|
index 7d91df704e..c4b15edd60 100644
|
|
--- a/dom/xslt/xslt/txExecutionState.h
|
|
+++ b/dom/xslt/xslt/txExecutionState.h
|
|
@@ -17,6 +17,7 @@
|
|
#include "txStylesheet.h"
|
|
#include "txXPathTreeWalker.h"
|
|
#include "nsTArray.h"
|
|
+#include "mozilla/Result.h"
|
|
|
|
class txAOutputHandlerFactory;
|
|
class txAXMLEventHandler;
|
|
@@ -115,13 +116,14 @@ class txExecutionState : public txIMatchContext {
|
|
}
|
|
|
|
// state-modification functions
|
|
- txInstruction* getNextInstruction();
|
|
+ mozilla::Result<txInstruction*, nsresult> getNextInstruction();
|
|
nsresult runTemplate(txInstruction* aInstruction);
|
|
nsresult runTemplate(txInstruction* aInstruction, txInstruction* aReturnTo);
|
|
void gotoInstruction(txInstruction* aNext);
|
|
void returnFromTemplate();
|
|
nsresult bindVariable(const txExpandedName& aName, txAExprResult* aValue);
|
|
void removeVariable(const txExpandedName& aName);
|
|
+ void stopProcessing() { mStopProcessing = true; }
|
|
|
|
txAXMLEventHandler* mOutputHandler;
|
|
txAXMLEventHandler* mResultHandler;
|
|
@@ -156,6 +158,7 @@ class txExecutionState : public txIMatchContext {
|
|
txKeyHash mKeyHash;
|
|
RefPtr<txResultRecycler> mRecycler;
|
|
bool mDisableLoads;
|
|
+ bool mStopProcessing = false;
|
|
|
|
static const int32_t kMaxRecursionDepth;
|
|
};
|
|
diff --git a/dom/xslt/xslt/txMozillaXSLTProcessor.cpp b/dom/xslt/xslt/txMozillaXSLTProcessor.cpp
|
|
index 1b22b1caf0..5d810471b6 100644
|
|
--- a/dom/xslt/xslt/txMozillaXSLTProcessor.cpp
|
|
+++ b/dom/xslt/xslt/txMozillaXSLTProcessor.cpp
|
|
@@ -538,6 +538,80 @@ already_AddRefed<Document> txMozillaXSLTProcessor::TransformToDocument(
|
|
return doc.forget();
|
|
}
|
|
|
|
+class XSLTProcessRequest final : public nsIRequest {
|
|
+ public:
|
|
+ explicit XSLTProcessRequest(txExecutionState* aState) : mState(aState) {}
|
|
+
|
|
+ NS_DECL_ISUPPORTS
|
|
+ NS_DECL_NSIREQUEST
|
|
+
|
|
+ void Done() { mState = nullptr; }
|
|
+
|
|
+ private:
|
|
+ ~XSLTProcessRequest() {}
|
|
+ txExecutionState* mState;
|
|
+};
|
|
+NS_IMPL_ISUPPORTS(XSLTProcessRequest, nsIRequest)
|
|
+
|
|
+NS_IMETHODIMP
|
|
+XSLTProcessRequest::GetName(nsACString& aResult) {
|
|
+ aResult.AssignLiteral("about:xslt-load-blocker");
|
|
+ return NS_OK;
|
|
+}
|
|
+
|
|
+NS_IMETHODIMP
|
|
+XSLTProcessRequest::IsPending(bool* _retval) {
|
|
+ *_retval = true;
|
|
+ return NS_OK;
|
|
+}
|
|
+
|
|
+NS_IMETHODIMP
|
|
+XSLTProcessRequest::GetStatus(nsresult* status) {
|
|
+ *status = NS_OK;
|
|
+ return NS_OK;
|
|
+}
|
|
+
|
|
+NS_IMETHODIMP
|
|
+XSLTProcessRequest::Cancel(nsresult status) {
|
|
+ mState->stopProcessing();
|
|
+ return NS_OK;
|
|
+}
|
|
+
|
|
+NS_IMETHODIMP
|
|
+XSLTProcessRequest::Suspend(void) { return NS_OK; }
|
|
+
|
|
+NS_IMETHODIMP
|
|
+XSLTProcessRequest::Resume(void) { return NS_OK; }
|
|
+
|
|
+NS_IMETHODIMP
|
|
+XSLTProcessRequest::GetLoadGroup(nsILoadGroup** aLoadGroup) {
|
|
+ *aLoadGroup = nullptr;
|
|
+ return NS_OK;
|
|
+}
|
|
+
|
|
+NS_IMETHODIMP
|
|
+XSLTProcessRequest::SetLoadGroup(nsILoadGroup* aLoadGroup) { return NS_OK; }
|
|
+
|
|
+NS_IMETHODIMP
|
|
+XSLTProcessRequest::GetLoadFlags(nsLoadFlags* aLoadFlags) {
|
|
+ *aLoadFlags = nsIRequest::LOAD_NORMAL;
|
|
+ return NS_OK;
|
|
+}
|
|
+
|
|
+NS_IMETHODIMP
|
|
+XSLTProcessRequest::SetLoadFlags(nsLoadFlags aLoadFlags) { return NS_OK; }
|
|
+
|
|
+NS_IMETHODIMP
|
|
+XSLTProcessRequest::GetTRRMode(nsIRequest::TRRMode* aTRRMode) {
|
|
+ return GetTRRModeImpl(aTRRMode);
|
|
+}
|
|
+
|
|
+NS_IMETHODIMP
|
|
+XSLTProcessRequest::SetTRRMode(nsIRequest::TRRMode aTRRMode) {
|
|
+ return SetTRRModeImpl(aTRRMode);
|
|
+}
|
|
+
|
|
+
|
|
nsresult txMozillaXSLTProcessor::TransformToDoc(Document** aResult,
|
|
bool aCreateDataDocument) {
|
|
UniquePtr<txXPathNode> sourceNode(
|
|
@@ -548,11 +622,31 @@ nsresult txMozillaXSLTProcessor::TransformToDoc(Document** aResult,
|
|
|
|
txExecutionState es(mStylesheet, IsLoadDisabled());
|
|
|
|
+ Document* sourceDoc = mSource->OwnerDoc();
|
|
+ nsCOMPtr<nsILoadGroup> loadGroup = sourceDoc->GetDocumentLoadGroup();
|
|
+ if (!loadGroup) {
|
|
+ nsCOMPtr<nsPIDOMWindowInner> win = do_QueryInterface(mOwner);
|
|
+ if (win && win->IsCurrentInnerWindow()) {
|
|
+ Document* doc = win->GetDoc();
|
|
+ if (doc) {
|
|
+ loadGroup = doc->GetDocumentLoadGroup();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (!loadGroup) {
|
|
+ return NS_ERROR_FAILURE;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ RefPtr<XSLTProcessRequest> xsltProcessRequest = new XSLTProcessRequest(&es);
|
|
+ loadGroup->AddRequest(xsltProcessRequest, nullptr);
|
|
+
|
|
+
|
|
// XXX Need to add error observers
|
|
|
|
// If aResult is non-null, we're a data document
|
|
- txToDocHandlerFactory handlerFactory(&es, mSource->OwnerDoc(), mObserver,
|
|
- aCreateDataDocument);
|
|
+ txToDocHandlerFactory handlerFactory(&es, sourceDoc, mObserver,
|
|
+ aCreateDataDocument);
|
|
es.mOutputHandlerFactory = &handlerFactory;
|
|
|
|
nsresult rv = es.init(*sourceNode, &mVariables);
|
|
@@ -562,6 +656,9 @@ nsresult txMozillaXSLTProcessor::TransformToDoc(Document** aResult,
|
|
rv = txXSLTProcessor::execute(es);
|
|
}
|
|
|
|
+ xsltProcessRequest->Done();
|
|
+ loadGroup->RemoveRequest(xsltProcessRequest, nullptr, NS_OK);
|
|
+
|
|
nsresult endRv = es.end(rv);
|
|
if (NS_SUCCEEDED(rv)) {
|
|
rv = endRv;
|
|
diff --git a/dom/xslt/xslt/txXSLTProcessor.cpp b/dom/xslt/xslt/txXSLTProcessor.cpp
|
|
index dfcdeb5595..4a5117efcf 100644
|
|
--- a/dom/xslt/xslt/txXSLTProcessor.cpp
|
|
+++ b/dom/xslt/xslt/txXSLTProcessor.cpp
|
|
@@ -31,12 +31,21 @@ void txXSLTProcessor::shutdown() { txHandlerTable::shutdown(); }
|
|
|
|
/* static */
|
|
nsresult txXSLTProcessor::execute(txExecutionState& aEs) {
|
|
- nsresult rv = NS_OK;
|
|
- txInstruction* instr;
|
|
- while ((instr = aEs.getNextInstruction())) {
|
|
- rv = instr->execute(aEs);
|
|
- NS_ENSURE_SUCCESS(rv, rv);
|
|
- }
|
|
-
|
|
- return NS_OK;
|
|
+
|
|
+ nsresult rv;
|
|
+ do {
|
|
+ mozilla::Result<txInstruction*, nsresult> result = aEs.getNextInstruction();
|
|
+ if (result.isErr()) {
|
|
+ return result.unwrapErr();
|
|
+ }
|
|
+
|
|
+ txInstruction* instr = result.unwrap();
|
|
+ if (!instr) {
|
|
+ return NS_OK;
|
|
+ }
|
|
+
|
|
+ rv = instr->execute(aEs);
|
|
+ } while (NS_SUCCEEDED(rv));
|
|
+
|
|
+ return rv;
|
|
}
|
|
--
|
|
2.27.0
|