Bug 1941002 - Check state before compiling/transforming. r=smaug a=pascalc

Differential Revision: https://phabricator.services.mozilla.com/D237260
This commit is contained in:
Peter Van der Beken 2025-02-23 07:54:06 +00:00
parent 1fa5bedc44
commit 79b4678302
3 changed files with 81 additions and 10 deletions

View file

@ -88,11 +88,13 @@ interface XSLTProcessor {
* the processor use the default-value for all parameters as specified in
* the stylesheet.
*/
[Throws]
undefined clearParameters();
/**
* Remove all parameters and stylesheets from this XSLTProcessor.
*/
[Throws]
undefined reset();
/**

View file

@ -5,6 +5,7 @@
#include "txMozillaXSLTProcessor.h"
#include "nsError.h"
#include "mozilla/AutoRestore.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/Document.h"
#include "nsIStringBundle.h"
@ -264,7 +265,8 @@ NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(txMozillaXSLTProcessor)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(txMozillaXSLTProcessor)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner, mSource)
tmp->Reset();
MOZ_RELEASE_ASSERT(tmp->mState == State::None);
tmp->Reset(IgnoreErrors());
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
@ -295,7 +297,10 @@ txMozillaXSLTProcessor::txMozillaXSLTProcessor(nsISupports* aOwner)
mCompileResult(NS_OK),
mFlags(0) {}
txMozillaXSLTProcessor::~txMozillaXSLTProcessor() { Reset(); }
txMozillaXSLTProcessor::~txMozillaXSLTProcessor() {
MOZ_RELEASE_ASSERT(mState == State::None);
Reset(IgnoreErrors());
}
NS_IMETHODIMP
txMozillaXSLTProcessor::SetTransformObserver(nsITransformObserver* aObserver) {
@ -474,6 +479,8 @@ class nsTransformBlockerEvent : public mozilla::Runnable {
}
NS_IMETHOD Run() override {
MOZ_RELEASE_ASSERT(mProcessor->mState ==
txMozillaXSLTProcessor::State::None);
mProcessor->TransformToDoc(nullptr, false);
return NS_OK;
}
@ -505,6 +512,13 @@ void txMozillaXSLTProcessor::ImportStylesheet(nsINode& aStyle,
return;
}
if (mState != State::None) {
aRv.ThrowInvalidStateError("Invalid call.");
return;
}
mozilla::AutoRestore<State> restore(mState);
mState = State::Compiling;
MOZ_ASSERT(!mEmbeddedStylesheetRoot);
mCompileResult = NS_OK;
@ -548,12 +562,21 @@ already_AddRefed<Document> txMozillaXSLTProcessor::TransformToDocument(
return nullptr;
}
if (mState != State::None) {
aRv.ThrowInvalidStateError("Invalid call.");
return nullptr;
}
nsresult rv = ensureStylesheet();
if (NS_WARN_IF(NS_FAILED(rv))) {
aRv.Throw(rv);
return nullptr;
}
MOZ_RELEASE_ASSERT(mState == State::None);
mozilla::AutoRestore<State> restore(mState);
mState = State::Transforming;
mSource = aSource.CloneNode(true, aRv);
if (aRv.Failed()) {
return nullptr;
@ -738,12 +761,21 @@ already_AddRefed<DocumentFragment> txMozillaXSLTProcessor::TransformToFragment(
return nullptr;
}
if (mState != State::None) {
aRv.ThrowInvalidStateError("Invalid call.");
return nullptr;
}
nsresult rv = ensureStylesheet();
if (NS_WARN_IF(NS_FAILED(rv))) {
aRv.Throw(rv);
return nullptr;
}
MOZ_RELEASE_ASSERT(mState == State::None);
mozilla::AutoRestore<State> restore(mState);
mState = State::Transforming;
nsCOMPtr<nsINode> source;
if (aCloneSource) {
source = aSource.CloneNode(true, aRv);
@ -792,6 +824,11 @@ void txMozillaXSLTProcessor::SetParameter(const nsAString& aNamespaceURI,
const nsAString& aLocalName,
const XSLTParameterValue& aValue,
ErrorResult& aError) {
if (mState != State::None) {
aError.ThrowInvalidStateError("Invalid call.");
return;
}
if (aValue.IsNode()) {
if (!nsContentUtils::CanCallerAccess(&aValue.GetAsNode())) {
aError.ThrowSecurityError("Caller is not allowed to access node.");
@ -880,6 +917,11 @@ void txMozillaXSLTProcessor::GetParameter(
void txMozillaXSLTProcessor::RemoveParameter(const nsAString& aNamespaceURI,
const nsAString& aLocalName,
ErrorResult& aRv) {
if (mState != State::None) {
aRv.ThrowInvalidStateError("Invalid call.");
return;
}
int32_t nsId = kNameSpaceID_Unknown;
nsresult rv =
nsNameSpaceManager::GetInstance()->RegisterNameSpace(aNamespaceURI, nsId);
@ -893,9 +935,21 @@ void txMozillaXSLTProcessor::RemoveParameter(const nsAString& aNamespaceURI,
mVariables.remove(varName);
}
void txMozillaXSLTProcessor::ClearParameters() { mVariables.clear(); }
void txMozillaXSLTProcessor::ClearParameters(ErrorResult& aError) {
if (mState != State::None) {
aError.ThrowInvalidStateError("Invalid call.");
return;
}
mVariables.clear();
}
void txMozillaXSLTProcessor::Reset(ErrorResult& aError) {
if (mState != State::None) {
aError.ThrowInvalidStateError("Invalid call.");
return;
}
void txMozillaXSLTProcessor::Reset() {
if (mStylesheetDocument) {
mStylesheetDocument->RemoveMutationObserver(this);
}
@ -1055,6 +1109,12 @@ void txMozillaXSLTProcessor::notifyError() {
}
nsresult txMozillaXSLTProcessor::ensureStylesheet() {
if (mState != State::None) {
return NS_ERROR_FAILURE;
}
mozilla::AutoRestore<State> restore(mState);
mState = State::Compiling;
if (mStylesheet) {
return NS_OK;
}

View file

@ -92,17 +92,17 @@ class txMozillaXSLTProcessor final : public nsIDocumentTransformer,
static already_AddRefed<txMozillaXSLTProcessor> Constructor(
const mozilla::dom::GlobalObject& aGlobal);
void ImportStylesheet(nsINode& stylesheet, mozilla::ErrorResult& aRv);
void ImportStylesheet(nsINode& aStylesheet, mozilla::ErrorResult& aRv);
already_AddRefed<mozilla::dom::DocumentFragment> TransformToFragment(
nsINode& aSource, mozilla::dom::Document& aDocument,
nsINode& aSource, mozilla::dom::Document& aOutput,
mozilla::ErrorResult& aRv) {
return TransformToFragment(aSource, true, aDocument, aRv);
return TransformToFragment(aSource, true, aOutput, aRv);
}
already_AddRefed<mozilla::dom::DocumentFragment> TransformToFragment(
nsINode& aSource, bool aCloneSource, mozilla::dom::Document& aOutput,
mozilla::ErrorResult& aRv);
already_AddRefed<mozilla::dom::Document> TransformToDocument(
nsINode& source, mozilla::ErrorResult& aRv);
nsINode& aSource, mozilla::ErrorResult& aRv);
void SetParameter(const nsAString& aNamespaceURI, const nsAString& aLocalName,
const XSLTParameterValue& aValue,
@ -112,8 +112,8 @@ class txMozillaXSLTProcessor final : public nsIDocumentTransformer,
mozilla::ErrorResult& aRv);
void RemoveParameter(const nsAString& aNamespaceURI,
const nsAString& aLocalName, mozilla::ErrorResult& aRv);
void ClearParameters();
void Reset();
void ClearParameters(mozilla::ErrorResult& aError);
void Reset(mozilla::ErrorResult& aError);
uint32_t Flags(mozilla::dom::SystemCallerGuarantee);
void SetFlags(uint32_t aFlags, mozilla::dom::SystemCallerGuarantee);
@ -136,6 +136,8 @@ class txMozillaXSLTProcessor final : public nsIDocumentTransformer,
static void Shutdown();
private:
friend class nsTransformBlockerEvent;
explicit txMozillaXSLTProcessor(nsISupports* aOwner);
/**
* Default destructor for txMozillaXSLTProcessor
@ -162,6 +164,13 @@ class txMozillaXSLTProcessor final : public nsIDocumentTransformer,
RefPtr<txResultRecycler> mRecycler;
uint32_t mFlags;
enum class State {
None,
Compiling,
Transforming,
};
State mState = State::None;
};
extern nsresult TX_LoadSheet(nsIURI* aUri, txMozillaXSLTProcessor* aProcessor,