Skip to content

Commit

Permalink
Bug 1864838 - Update our Sanitizer to the new proposed WebIDL. r=emil…
Browse files Browse the repository at this point in the history
…io,freddyb

The new proposed WebIDL is at WICG/sanitizer-api#181 (comment).
Sadly we don't have a real spec for this yet. Luckily this is mostly
just a renaming. The biggest change is that every <element> in elements: now has a list of allowed and removed attributes.

Differential Revision: https://phabricator.services.mozilla.com/D193642

UltraBlame original commit: 8c7aa601f08a38022d337a34788b7e75e5ca4aed
  • Loading branch information
marco-c committed Nov 30, 2023
1 parent cca2705 commit 9a6c430
Show file tree
Hide file tree
Showing 5 changed files with 216 additions and 156 deletions.
65 changes: 34 additions & 31 deletions dom/base/Element.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4949,43 +4949,46 @@ void Element::SetHTML(const nsAString& aInnerHTML,
true, -1, getter_AddRefs(fragment));
}

if (!aError.Failed()) {



nsAutoScriptBlockerSuppressNodeRemoved scriptBlocker;
if (aError.Failed()) {
return;
}

int32_t oldChildCount = static_cast<int32_t>(target->GetChildCount());



nsAutoScriptBlockerSuppressNodeRemoved scriptBlocker;

RefPtr<Sanitizer> sanitizer;
if (!aOptions.mSanitizer.WasPassed()) {
nsCOMPtr<nsIGlobalObject> global = GetOwnerGlobal();
if (!global) {
aError.ThrowInvalidStateError("Missing owner global.");
return;
}
sanitizer = Sanitizer::New(global, {}, aError);
if (aError.Failed()) {
return;
}
} else {
sanitizer = &aOptions.mSanitizer.Value();
}
int32_t oldChildCount = static_cast<int32_t>(target->GetChildCount());

sanitizer->SanitizeFragment(fragment, aError);
if (aError.Failed()) {
return;
}
nsCOMPtr<nsIGlobalObject> global = GetOwnerGlobal();
if (!global) {
aError.ThrowInvalidStateError("Missing owner global.");
return;
}

target->AppendChild(*fragment, aError);
if (aError.Failed()) {
return;
}
RefPtr<Sanitizer> sanitizer;
if (aOptions.mSanitizer.WasPassed()) {
sanitizer = Sanitizer::New(global, aOptions.mSanitizer.Value(), aError);
} else {
sanitizer = Sanitizer::New(global, {}, aError);
}
if (aError.Failed()) {
return;
}

mb.NodesAdded();
nsContentUtils::FireMutationEventsForDirectParsing(doc, target,
oldChildCount);
sanitizer->SanitizeFragment(fragment, aError);
if (aError.Failed()) {
return;
}

target->AppendChild(*fragment, aError);
if (aError.Failed()) {
return;
}

mb.NodesAdded();
nsContentUtils::FireMutationEventsForDirectParsing(doc, target,
oldChildCount);
}

bool Element::Translate() const {
Expand Down
213 changes: 127 additions & 86 deletions dom/base/nsTreeSanitizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1587,18 +1587,18 @@ bool nsTreeSanitizer::MustFlattenForSanitizerAPI(int32_t aNamespace,



if (mBlockElements &&
MatchesElementName(*mBlockElements, aNamespace, aLocal)) {
if (mReplaceWithChildrenElements &&
MatchesElementName(*mReplaceWithChildrenElements, aNamespace, aLocal)) {
return true;
}




if (mAllowElements) {
if (mElements) {


if (!MatchesElementName(*mAllowElements, aNamespace, aLocal)) {
if (!mElements->Contains(ElementName(aNamespace, aLocal))) {
return true;
}
} else {
Expand Down Expand Up @@ -1761,7 +1761,8 @@ bool nsTreeSanitizer::MustPruneForSanitizerAPI(int32_t aNamespace,
}


if (mDropElements && MatchesElementName(*mDropElements, aNamespace, aLocal)) {
if (mRemoveElements &&
MatchesElementName(*mRemoveElements, aNamespace, aLocal)) {
return true;
}

Expand Down Expand Up @@ -1971,39 +1972,10 @@ bool nsTreeSanitizer::MatchesElementName(ElementNameSet& aNames,
return aNames.Contains(ElementName(aNamespace, aLocalName));
}


bool nsTreeSanitizer::MatchesAttributeMatchList(
AttributesToElementsMap& aMatchList, Element& aElement,
int32_t aAttrNamespace, nsAtom* aAttrLocalName) {


ElementNameSet* names;
if (auto lookup =
aMatchList.Lookup(AttributeName(aAttrNamespace, aAttrLocalName))) {
names = lookup->get();
} else {
return false;
}








int32_t namespaceID = aElement.NodeInfo()->NamespaceID();
RefPtr<nsAtom> nameAtom = aElement.NodeInfo()->NameAtom();






if (!names) {
return true;
}
return MatchesElementName(*names, namespaceID, nameAtom);
bool nsTreeSanitizer::MatchesAttributeName(AttributeNameSet& aNames,
int32_t aNamespace,
nsAtom* aLocalName) {
return aNames.Contains(AttributeName(aNamespace, aLocalName));
}


Expand All @@ -2026,19 +1998,42 @@ bool nsTreeSanitizer::MustDropAttribute(Element* aElement,



if (mDropAttributes &&
MatchesAttributeMatchList(*mDropAttributes, *aElement, aAttrNamespace,
aAttrLocalName)) {

if (mElements) {
int32_t namespaceID = aElement->NodeInfo()->NamespaceID();
RefPtr<nsAtom> nameAtom = aElement->NodeInfo()->NameAtom();

if (auto entry = mElements->Lookup(ElementName(namespaceID, nameAtom))) {
if (entry->mRemoveAttributes &&
MatchesAttributeName(*entry->mRemoveAttributes, aAttrNamespace,
aAttrLocalName)) {
return true;
}

if (entry->mAttributes) {
if (!MatchesAttributeName(*entry->mAttributes, aAttrNamespace,
aAttrLocalName)) {
return true;
}

}
}
}



if (mRemoveAttributes &&
MatchesAttributeName(*mRemoveAttributes, aAttrNamespace,
aAttrLocalName)) {
return true;
}


if (mAllowAttributes) {
if (mAttributes) {



if (!MatchesAttributeMatchList(*mAllowAttributes, *aElement, aAttrNamespace,
aAttrLocalName)) {
if (!MatchesAttributeName(*mAttributes, aAttrNamespace, aAttrLocalName)) {
return true;
}
} else {
Expand Down Expand Up @@ -2462,6 +2457,12 @@ void nsTreeSanitizer::ReleaseStatics() {
static int32_t ConvertNamespaceString(const nsAString& aNamespace,
bool aForAttribute,
mozilla::ErrorResult& aRv) {
if (aNamespace.IsVoid()) {


return kNameSpaceID_None;
}

int32_t namespaceID = nsNameSpaceManager::GetInstance()->GetNameSpaceID(
aNamespace, false);
if (namespaceID == kNameSpaceID_XHTML || namespaceID == kNameSpaceID_MathML ||
Expand Down Expand Up @@ -2502,47 +2503,86 @@ UniquePtr<nsTreeSanitizer::ElementNameSet> nsTreeSanitizer::ConvertElements(
set->Insert(elemName);
}
}

return set;
}

UniquePtr<nsTreeSanitizer::ElementNameSet> nsTreeSanitizer::ConvertElements(
const OwningStarOrStringOrSanitizerElementNamespaceSequence& aElements,
UniquePtr<nsTreeSanitizer::ElementsToAttributesMap>
nsTreeSanitizer::ConvertElementsWithAttributes(
const nsTArray<OwningStringOrSanitizerElementNamespaceWithAttributes>&
aElements,
mozilla::ErrorResult& aRv) {
if (aElements.IsStar()) {
return nullptr;
}
return ConvertElements(
aElements.GetAsStringOrSanitizerElementNamespaceSequence(), aRv);
}
auto map = MakeUnique<ElementsToAttributesMap>();

UniquePtr<nsTreeSanitizer::AttributesToElementsMap>
nsTreeSanitizer::ConvertAttributes(
const nsTArray<SanitizerAttribute>& aAttributes, ErrorResult& aRv) {
auto map = MakeUnique<AttributesToElementsMap>();
for (const auto& entry : aElements) {
if (entry.IsString()) {
RefPtr<nsAtom> nameAtom = NS_AtomizeMainThread(entry.GetAsString());

ElementName elemName(kNameSpaceID_XHTML, std::move(nameAtom));

map->InsertOrUpdate(elemName, ElementWithAttributes{});
} else {
const auto& elemNamespace =
entry.GetAsSanitizerElementNamespaceWithAttributes();

for (const auto& entry : aAttributes) {

int32_t namespaceID = kNameSpaceID_None;
if (!entry.mNamespace.IsVoid()) {
namespaceID = ConvertNamespaceString(entry.mNamespace, true, aRv);
ElementWithAttributes elemWithAttributes;

if (elemNamespace.mAttributes.WasPassed()) {
elemWithAttributes.mAttributes =
ConvertAttributes(elemNamespace.mAttributes.Value(), aRv);
if (aRv.Failed()) {
return {};
}
}

if (elemNamespace.mRemoveAttributes.WasPassed()) {
elemWithAttributes.mRemoveAttributes =
ConvertAttributes(elemNamespace.mRemoveAttributes.Value(), aRv);
if (aRv.Failed()) {
return {};
}
}

int32_t namespaceID =
ConvertNamespaceString(elemNamespace.mNamespace, false, aRv);
if (aRv.Failed()) {
return {};
}
}
RefPtr<nsAtom> attrAtom = NS_AtomizeMainThread(entry.mName);
AttributeName attrName(namespaceID, std::move(attrAtom));

UniquePtr<ElementNameSet> elements = ConvertElements(entry.mElements, aRv);
if (aRv.Failed()) {
return {};
RefPtr<nsAtom> nameAtom = NS_AtomizeMainThread(elemNamespace.mName);
ElementName elemName(namespaceID, std::move(nameAtom));

map->InsertOrUpdate(elemName, std::move(elemWithAttributes));
}
map->InsertOrUpdate(attrName, std::move(elements));
}

return map;
}

UniquePtr<nsTreeSanitizer::AttributeNameSet> nsTreeSanitizer::ConvertAttributes(
const nsTArray<OwningStringOrSanitizerAttributeNamespace>& aAttributes,
ErrorResult& aRv) {
auto set = MakeUnique<AttributeNameSet>(aAttributes.Length());
for (const auto& entry : aAttributes) {
if (entry.IsString()) {
RefPtr<nsAtom> nameAtom = NS_AtomizeMainThread(entry.GetAsString());

AttributeName attrName(kNameSpaceID_None, std::move(nameAtom));
set->Insert(attrName);
} else {
const auto& attrNamespace = entry.GetAsSanitizerAttributeNamespace();
int32_t namespaceID =
ConvertNamespaceString(attrNamespace.mNamespace, true, aRv);
if (aRv.Failed()) {
return {};
}
RefPtr<nsAtom> attrAtom = NS_AtomizeMainThread(attrNamespace.mName);
AttributeName attrName(namespaceID, std::move(attrAtom));
set->Insert(attrName);
}
}
return set;
}

void nsTreeSanitizer::WithWebSanitizerOptions(
nsIGlobalObject* aGlobal, const mozilla::dom::SanitizerConfig& aOptions,
ErrorResult& aRv) {
Expand All @@ -2555,46 +2595,47 @@ void nsTreeSanitizer::WithWebSanitizerOptions(

mIsForSanitizerAPI = true;

if (aOptions.mAllowComments.WasPassed()) {
mAllowComments = aOptions.mAllowComments.Value();
if (aOptions.mComments.WasPassed()) {
mAllowComments = aOptions.mComments.Value();
}
if (aOptions.mAllowCustomElements.WasPassed()) {
mAllowCustomElements = aOptions.mAllowCustomElements.Value();
if (aOptions.mCustomElements.WasPassed()) {
mAllowCustomElements = aOptions.mCustomElements.Value();
}
if (aOptions.mAllowUnknownMarkup.WasPassed()) {
mAllowUnknownMarkup = aOptions.mAllowUnknownMarkup.Value();
if (aOptions.mUnknownMarkup.WasPassed()) {
mAllowUnknownMarkup = aOptions.mUnknownMarkup.Value();
}

if (aOptions.mAllowElements.WasPassed()) {
mAllowElements = ConvertElements(aOptions.mAllowElements.Value(), aRv);
if (aOptions.mElements.WasPassed()) {
mElements = ConvertElementsWithAttributes(aOptions.mElements.Value(), aRv);
if (aRv.Failed()) {
return;
}
}

if (aOptions.mBlockElements.WasPassed()) {
mBlockElements = ConvertElements(aOptions.mBlockElements.Value(), aRv);
if (aOptions.mRemoveElements.WasPassed()) {
mRemoveElements = ConvertElements(aOptions.mRemoveElements.Value(), aRv);
if (aRv.Failed()) {
return;
}
}

if (aOptions.mDropElements.WasPassed()) {
mDropElements = ConvertElements(aOptions.mDropElements.Value(), aRv);
if (aOptions.mReplaceWithChildrenElements.WasPassed()) {
mReplaceWithChildrenElements =
ConvertElements(aOptions.mReplaceWithChildrenElements.Value(), aRv);
if (aRv.Failed()) {
return;
}
}

if (aOptions.mAllowAttributes.WasPassed()) {
mAllowAttributes =
ConvertAttributes(aOptions.mAllowAttributes.Value(), aRv);
if (aOptions.mAttributes.WasPassed()) {
mAttributes = ConvertAttributes(aOptions.mAttributes.Value(), aRv);
if (aRv.Failed()) {
return;
}
}

if (aOptions.mDropAttributes.WasPassed()) {
mDropAttributes = ConvertAttributes(aOptions.mDropAttributes.Value(), aRv);
if (aOptions.mRemoveAttributes.WasPassed()) {
mRemoveAttributes =
ConvertAttributes(aOptions.mRemoveAttributes.Value(), aRv);
}
}
Loading

0 comments on commit 9a6c430

Please sign in to comment.