Bug 1782910 - Sanitizer: Implement the element matches an element name. r=emilio
This is still missing the part that normalizes lower-cased svg/mathml names. Differential Revision: https://phabricator.services.mozilla.com/D154654
This commit is contained in:
@@ -1590,8 +1590,8 @@ bool nsTreeSanitizer::MustFlattenForSanitizerAPI(int32_t aNamespace,
|
||||
|
||||
// Step 6. If element matches any name in config["blockElements"]: Return
|
||||
// block.
|
||||
// TODO(bug 1782910): "matches" is not really contains!
|
||||
if (mBlockElements && mBlockElements->Contains(aLocal)) {
|
||||
if (mBlockElements &&
|
||||
MatchesElementName(*mBlockElements, aNamespace, aLocal)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1601,19 +1601,20 @@ bool nsTreeSanitizer::MustFlattenForSanitizerAPI(int32_t aNamespace,
|
||||
if (mAllowElements) {
|
||||
// Step 9. If element does not match any name in allow list:
|
||||
// Return block.
|
||||
// TODO(bug 1782910): matches
|
||||
if (!mAllowElements->Contains(aLocal)) {
|
||||
if (!MatchesElementName(*mAllowElements, aNamespace, aLocal)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
} else {
|
||||
// Step 8.2. Otherwise: Set allow list to the default configuration's
|
||||
// element allow list.
|
||||
|
||||
// Step 9. If element does not match any name in allow list:
|
||||
// Return block.
|
||||
// TODO(bug 1782910): matches
|
||||
if (!sDefaultConfigurationElementAllowlist->Contains(aLocal)) {
|
||||
|
||||
// The default configuration only contains HTML elements, so we can
|
||||
// reject everything else.
|
||||
if (aNamespace != kNameSpaceID_XHTML ||
|
||||
!sDefaultConfigurationElementAllowlist->Contains(aLocal)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1763,8 +1764,7 @@ bool nsTreeSanitizer::MustPruneForSanitizerAPI(int32_t aNamespace,
|
||||
}
|
||||
|
||||
// Step 5. If element matches any name in config["dropElements"]: Return drop.
|
||||
// TODO(bug 1782910): "matches" is not really contains!
|
||||
if (mDropElements && mDropElements->Contains(aLocal)) {
|
||||
if (mDropElements && MatchesElementName(*mDropElements, aNamespace, aLocal)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1964,34 +1964,41 @@ void nsTreeSanitizer::SanitizeAttributes(mozilla::dom::Element* aElement,
|
||||
}
|
||||
}
|
||||
|
||||
// https://wicg.github.io/sanitizer-api/#element-matches-an-element-name
|
||||
bool nsTreeSanitizer::MatchesElementName(ElementNameSet& aNames,
|
||||
int32_t aNamespace,
|
||||
nsAtom* aLocalName) {
|
||||
return aNames.Contains(ElementName(aNamespace, aLocalName));
|
||||
}
|
||||
|
||||
// https://wicg.github.io/sanitizer-api/#attribute-match-list
|
||||
bool nsTreeSanitizer::MatchesAttributeMatchList(
|
||||
ElementToAttributeSetTable& aMatchList, Element& aElement,
|
||||
int32_t aAttrNamespace, nsAtom* aAttrLocalName) {
|
||||
// Step 1. If attribute’s local name does not match the attribute match list
|
||||
// list’s key and if the key is not "*": Return false.
|
||||
DynamicAtomsTable* elements;
|
||||
ElementNameSet* names;
|
||||
if (auto lookup = aMatchList.Lookup(aAttrLocalName)) {
|
||||
elements = lookup->get();
|
||||
names = lookup->get();
|
||||
} else if (auto lookup = aMatchList.Lookup(nsGkAtoms::_asterisk)) {
|
||||
elements = lookup->get();
|
||||
names = lookup->get();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 2. Let element be the attribute’s Element.
|
||||
// Step 3. Let element name be element’s local name.
|
||||
nsAtom* elemName = aElement.NodeInfo()->NameAtom();
|
||||
|
||||
// Step 4. If element is a in either the SVG or MathML namespaces (i.e., it’s
|
||||
// a foreign element), then prefix element name with the appropriate namespace
|
||||
// designator plus a whitespace character.
|
||||
// TODO(bug 1784040) Namespace handling.
|
||||
int32_t namespaceID = aElement.NodeInfo()->NamespaceID();
|
||||
RefPtr<nsAtom> nameAtom = aElement.NodeInfo()->NameAtom();
|
||||
ElementName elemName(namespaceID, nameAtom);
|
||||
|
||||
// Step 5. If list’s value does not contain element name and value is not
|
||||
// ["*"]: Return false.
|
||||
if (!elements->Contains(elemName) &&
|
||||
!elements->Contains(nsGkAtoms::_asterisk)) {
|
||||
if (!names->Contains(elemName) &&
|
||||
!names->Contains(ElementName(kNameSpaceID_XHTML, nsGkAtoms::_asterisk))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2452,6 +2459,50 @@ void nsTreeSanitizer::ReleaseStatics() {
|
||||
NS_IF_RELEASE(sNullPrincipal);
|
||||
}
|
||||
|
||||
UniquePtr<nsTreeSanitizer::ElementNameSet> nsTreeSanitizer::ConvertElementNames(
|
||||
const Sequence<nsString>& aNames) {
|
||||
auto names = MakeUnique<ElementNameSet>(aNames.Length());
|
||||
|
||||
// https://wicg.github.io/sanitizer-api/#normalize-element-name
|
||||
for (const nsString& name : aNames) {
|
||||
// Step 1. Let tokens be the result of strictly splitting name on the
|
||||
// delimiter ":" (U+003A).
|
||||
int32_t index = name.FindChar(':');
|
||||
|
||||
// Step 2. If tokens’ size is 1, then return tokens[0].
|
||||
if (index == kNotFound) {
|
||||
RefPtr<nsAtom> nameAtom = NS_AtomizeMainThread(name);
|
||||
ElementName elemName(kNameSpaceID_XHTML, std::move(nameAtom));
|
||||
names->Insert(elemName);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Step 3. If tokens’ size is 2 and tokens[0] is either "svg" or "math",
|
||||
// then:
|
||||
if (name.FindChar(':', index + 1) == kNotFound) {
|
||||
auto prefix = Substring(name, 0, index);
|
||||
// Step 3.1. Adjust tokens[1] as described in the "any other start tag"
|
||||
// branch of the rules for parsing tokens in foreign content subchapter in
|
||||
// the HTML parsing spec. Step 3.2 Return the concatenation of the list
|
||||
// «|tokens|[0],":" (U+003A),|tokens|[1]».
|
||||
// TODO
|
||||
RefPtr<nsAtom> nameAtom =
|
||||
NS_AtomizeMainThread(Substring(name, index + 1));
|
||||
if (prefix.EqualsLiteral("svg")) {
|
||||
ElementName elemName(kNameSpaceID_SVG, std::move(nameAtom));
|
||||
names->Insert(elemName);
|
||||
} else if (prefix.EqualsLiteral("math")) {
|
||||
ElementName elemName(kNameSpaceID_MathML, std::move(nameAtom));
|
||||
names->Insert(elemName);
|
||||
}
|
||||
}
|
||||
|
||||
// Step 4. Return null.
|
||||
// Nothing is inserted and name is skipped.
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
void nsTreeSanitizer::WithWebSanitizerOptions(
|
||||
nsIGlobalObject* aGlobal, const mozilla::dom::SanitizerConfig& aOptions) {
|
||||
if (StaticPrefs::dom_security_sanitizer_logging()) {
|
||||
@@ -2478,46 +2529,25 @@ void nsTreeSanitizer::WithWebSanitizerOptions(
|
||||
}
|
||||
|
||||
if (aOptions.mAllowElements.WasPassed()) {
|
||||
const Sequence<nsString>& allowedElements = aOptions.mAllowElements.Value();
|
||||
mAllowElements = MakeUnique<DynamicAtomsTable>(allowedElements.Length());
|
||||
for (const nsString& elem : allowedElements) {
|
||||
RefPtr<nsAtom> elAsAtom = NS_AtomizeMainThread(elem);
|
||||
mAllowElements->Insert(elAsAtom);
|
||||
}
|
||||
mAllowElements = ConvertElementNames(aOptions.mAllowElements.Value());
|
||||
}
|
||||
|
||||
if (aOptions.mBlockElements.WasPassed()) {
|
||||
const Sequence<nsString>& blockedElements = aOptions.mBlockElements.Value();
|
||||
mBlockElements = MakeUnique<DynamicAtomsTable>(blockedElements.Length());
|
||||
for (const nsString& elem : blockedElements) {
|
||||
RefPtr<nsAtom> elAsAtom = NS_AtomizeMainThread(elem);
|
||||
mBlockElements->Insert(elAsAtom);
|
||||
}
|
||||
mBlockElements = ConvertElementNames(aOptions.mBlockElements.Value());
|
||||
}
|
||||
|
||||
if (aOptions.mDropElements.WasPassed()) {
|
||||
const Sequence<nsString>& dropElements = aOptions.mDropElements.Value();
|
||||
mDropElements = MakeUnique<DynamicAtomsTable>(dropElements.Length());
|
||||
for (const nsString& elem : dropElements) {
|
||||
RefPtr<nsAtom> elAsAtom = NS_AtomizeMainThread(elem);
|
||||
mDropElements->Insert(elAsAtom);
|
||||
}
|
||||
mDropElements = ConvertElementNames(aOptions.mDropElements.Value());
|
||||
}
|
||||
|
||||
if (aOptions.mAllowAttributes.WasPassed()) {
|
||||
const Record<nsString, Sequence<nsString>>& allowedAttributes =
|
||||
aOptions.mAllowAttributes.Value();
|
||||
mAllowedAttributes = MakeUnique<ElementToAttributeSetTable>();
|
||||
nsAutoString name;
|
||||
for (const auto& entries : allowedAttributes.Entries()) {
|
||||
UniquePtr<DynamicAtomsTable> elems =
|
||||
MakeUnique<DynamicAtomsTable>(allowedAttributes.Entries().Length());
|
||||
for (const auto& elem : entries.mValue) {
|
||||
RefPtr<nsAtom> elAsAtom = NS_AtomizeMainThread(elem);
|
||||
elems->Insert(elAsAtom);
|
||||
}
|
||||
RefPtr<nsAtom> attrAtom = NS_AtomizeMainThread(entries.mKey);
|
||||
mAllowedAttributes->InsertOrUpdate(attrAtom, std::move(elems));
|
||||
for (const auto& entry : allowedAttributes.Entries()) {
|
||||
RefPtr<nsAtom> attrAtom = NS_AtomizeMainThread(entry.mKey);
|
||||
UniquePtr<ElementNameSet> elements = ConvertElementNames(entry.mValue);
|
||||
mAllowedAttributes->InsertOrUpdate(attrAtom, std::move(elements));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2525,16 +2555,10 @@ void nsTreeSanitizer::WithWebSanitizerOptions(
|
||||
const Record<nsString, Sequence<nsString>>& droppedAttributes =
|
||||
aOptions.mDropAttributes.Value();
|
||||
mDroppedAttributes = MakeUnique<ElementToAttributeSetTable>();
|
||||
nsAutoString name;
|
||||
for (const auto& entries : droppedAttributes.Entries()) {
|
||||
UniquePtr<DynamicAtomsTable> elems =
|
||||
MakeUnique<DynamicAtomsTable>(droppedAttributes.Entries().Length());
|
||||
for (const auto& elem : entries.mValue) {
|
||||
RefPtr<nsAtom> elAsAtom = NS_AtomizeMainThread(elem);
|
||||
elems->Insert(elAsAtom);
|
||||
}
|
||||
RefPtr<nsAtom> attrAtom = NS_AtomizeMainThread(entries.mKey);
|
||||
mDroppedAttributes->InsertOrUpdate(attrAtom, std::move(elems));
|
||||
for (const auto& entry : droppedAttributes.Entries()) {
|
||||
RefPtr<nsAtom> attrAtom = NS_AtomizeMainThread(entry.mKey);
|
||||
UniquePtr<ElementNameSet> elements = ConvertElementNames(entry.mValue);
|
||||
mDroppedAttributes->InsertOrUpdate(attrAtom, std::move(elements));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "nsTArray.h"
|
||||
#include "nsTHashSet.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/dom/NameSpaceConstants.h"
|
||||
#include "mozilla/dom/SanitizerBinding.h"
|
||||
|
||||
class nsIContent;
|
||||
@@ -129,17 +130,44 @@ class nsTreeSanitizer {
|
||||
return aAtom->IsStatic() && GetEntry(aAtom->AsStatic());
|
||||
}
|
||||
};
|
||||
// Use this table for user-defined lists
|
||||
class DynamicAtomsTable : public nsTHashSet<RefPtr<nsAtom>> {
|
||||
public:
|
||||
explicit DynamicAtomsTable(uint32_t aLength)
|
||||
: nsTHashSet<RefPtr<nsAtom>>(aLength) {}
|
||||
|
||||
bool Contains(nsAtom* aAtom) { return GetEntry(aAtom); }
|
||||
// The name of an element combined with its namespace.
|
||||
class ElementName : public PLDHashEntryHdr {
|
||||
public:
|
||||
using KeyType = const ElementName&;
|
||||
using KeyTypePointer = const ElementName*;
|
||||
|
||||
explicit ElementName(KeyTypePointer aKey)
|
||||
: mNamespaceID(aKey->mNamespaceID), mLocalName(aKey->mLocalName) {}
|
||||
ElementName(int32_t aNamespaceID, RefPtr<nsAtom> aLocalName)
|
||||
: mNamespaceID(aNamespaceID), mLocalName(std::move(aLocalName)) {}
|
||||
ElementName(ElementName&&) = default;
|
||||
~ElementName() = default;
|
||||
|
||||
bool KeyEquals(KeyTypePointer aKey) const {
|
||||
return mNamespaceID == aKey->mNamespaceID &&
|
||||
mLocalName == aKey->mLocalName;
|
||||
}
|
||||
|
||||
static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
|
||||
static PLDHashNumber HashKey(KeyTypePointer aKey) {
|
||||
if (!aKey) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return mozilla::HashGeneric(aKey->mNamespaceID, aKey->mLocalName.get());
|
||||
}
|
||||
|
||||
enum { ALLOW_MEMMOVE = true };
|
||||
|
||||
private:
|
||||
int32_t mNamespaceID = kNameSpaceID_None;
|
||||
RefPtr<nsAtom> mLocalName;
|
||||
};
|
||||
|
||||
using ElementNameSet = nsTHashSet<ElementName>;
|
||||
using ElementToAttributeSetTable =
|
||||
nsTHashMap<RefPtr<nsAtom>, mozilla::UniquePtr<DynamicAtomsTable>>;
|
||||
nsTHashMap<RefPtr<nsAtom>, mozilla::UniquePtr<ElementNameSet>>;
|
||||
|
||||
void SanitizeChildren(nsINode* aRoot);
|
||||
|
||||
@@ -249,11 +277,16 @@ class nsTreeSanitizer {
|
||||
*/
|
||||
static void RemoveAllAttributesFromDescendants(mozilla::dom::Element*);
|
||||
|
||||
static bool MatchesElementName(ElementNameSet& aNames, int32_t aNamespace,
|
||||
nsAtom* aLocalName);
|
||||
static bool MatchesAttributeMatchList(ElementToAttributeSetTable& aMatchList,
|
||||
mozilla::dom::Element& aElement,
|
||||
int32_t aAttrNamespace,
|
||||
nsAtom* aAttrLocalName);
|
||||
|
||||
static mozilla::UniquePtr<ElementNameSet> ConvertElementNames(
|
||||
const mozilla::dom::Sequence<nsString>& aNames);
|
||||
|
||||
/**
|
||||
* Log a Console Service message to indicate we removed something.
|
||||
* If you pass an element and/or attribute, their information will
|
||||
@@ -338,13 +371,13 @@ class nsTreeSanitizer {
|
||||
bool mAllowUnknownMarkup = false;
|
||||
|
||||
// An allow-list of elements to keep.
|
||||
mozilla::UniquePtr<DynamicAtomsTable> mAllowElements;
|
||||
mozilla::UniquePtr<ElementNameSet> mAllowElements;
|
||||
|
||||
// A deny-list of elements to block. (aka flatten)
|
||||
mozilla::UniquePtr<DynamicAtomsTable> mBlockElements;
|
||||
mozilla::UniquePtr<ElementNameSet> mBlockElements;
|
||||
|
||||
// A deny-list of elements to drop. (aka prune)
|
||||
mozilla::UniquePtr<DynamicAtomsTable> mDropElements;
|
||||
mozilla::UniquePtr<ElementNameSet> mDropElements;
|
||||
|
||||
// An allow-list of attributes to keep.
|
||||
mozilla::UniquePtr<ElementToAttributeSetTable> mAllowedAttributes;
|
||||
|
||||
@@ -14,79 +14,22 @@
|
||||
[Attribute names in config item: dropAttributes]
|
||||
expected: FAIL
|
||||
|
||||
[Namespaced elements #0: allowElements: ["p"\]]
|
||||
expected: FAIL
|
||||
|
||||
[Namespaced elements #1: allowElements: ["svg"\]]
|
||||
expected: FAIL
|
||||
|
||||
[Namespaced elements #2: allowElements: ["svg:svg"\]]
|
||||
expected: FAIL
|
||||
|
||||
[Namespaced elements #3: allowElements: ["math"\]]
|
||||
expected: FAIL
|
||||
|
||||
[Namespaced elements #4: allowElements: ["svg:math"\]]
|
||||
expected: FAIL
|
||||
|
||||
[Namespaced elements #5: allowElements: ["math:math"\]]
|
||||
expected: FAIL
|
||||
|
||||
[Namespaced elements #6: allowElements: ["potato:math"\]]
|
||||
expected: FAIL
|
||||
|
||||
[Namespaced elements #7: allowElements: ["potato:math"\]]
|
||||
expected: FAIL
|
||||
|
||||
[Namespaced attributes #0: allowAttributes: {"style": ["*"\]}]
|
||||
expected: FAIL
|
||||
|
||||
[Namespaced attributes #1: allowAttributes: {"href": ["*"\]}]
|
||||
expected: FAIL
|
||||
|
||||
[Namespaced attributes #2: allowAttributes: {"xlink:href": ["*"\]}]
|
||||
expected: FAIL
|
||||
|
||||
[Namespaced attributes #3: allowAttributes: {"potato:href": ["*"\]}]
|
||||
expected: FAIL
|
||||
|
||||
[Namespaced attributes #4: allowAttributes: {"xlink:href": ["*"\]}]
|
||||
expected: FAIL
|
||||
|
||||
[Namespaced attributes #5: allowAttributes: {"href": ["*"\]}]
|
||||
expected: FAIL
|
||||
|
||||
[Mixed-case element names #0: "svg:feBlend"]
|
||||
expected: FAIL
|
||||
|
||||
[Mixed-case element names #0: "svg:feblend"]
|
||||
expected: FAIL
|
||||
|
||||
[Mixed-case element names #0: "SVG:FEBLEND"]
|
||||
[Lower-case element names #0: "svg:feblend"]
|
||||
expected: FAIL
|
||||
|
||||
[Mixed case element names #0: "svg:feBlend" is preserved in config.]
|
||||
expected: FAIL
|
||||
|
||||
[Mixed-case element names #1: "svg:feColorMatrix"]
|
||||
expected: FAIL
|
||||
|
||||
[Mixed-case element names #1: "svg:fecolormatrix"]
|
||||
expected: FAIL
|
||||
|
||||
[Mixed-case element names #1: "SVG:FECOLORMATRIX"]
|
||||
[Lower-case element names #1: "svg:fecolormatrix"]
|
||||
expected: FAIL
|
||||
|
||||
[Mixed case element names #1: "svg:feColorMatrix" is preserved in config.]
|
||||
expected: FAIL
|
||||
|
||||
[Mixed-case element names #2: "svg:textPath"]
|
||||
expected: FAIL
|
||||
|
||||
[Mixed-case element names #2: "svg:textpath"]
|
||||
expected: FAIL
|
||||
|
||||
[Mixed-case element names #2: "SVG:TEXTPATH"]
|
||||
[Lower-case element names #2: "svg:textpath"]
|
||||
expected: FAIL
|
||||
|
||||
[Mixed case element names #2: "svg:textPath" is preserved in config.]
|
||||
|
||||
@@ -65,9 +65,12 @@
|
||||
[ "potato:math", "<potato:math>Hello</potato:math>", "Hello" ],
|
||||
].forEach(([elem, probe, expected], index) => {
|
||||
test(t => {
|
||||
const sanitizer = new Sanitizer({allowElements: [elem]});
|
||||
assert_equals(sanitizer.sanitizeFor("template", probe).innerHTML,
|
||||
expected ?? probe);
|
||||
const sanitizer = new Sanitizer({allowElements: [elem],
|
||||
// TODO(https://github.com/WICG/sanitizer-api/issues/167)
|
||||
allowUnknownMarkup: true});
|
||||
const template = document.createElement("template");
|
||||
template.setHTML(probe, {sanitizer});
|
||||
assert_equals(template.innerHTML, expected ?? probe);
|
||||
}, `Namespaced elements #${index}: allowElements: ["${elem}"]`);
|
||||
});
|
||||
|
||||
@@ -81,39 +84,46 @@
|
||||
[ "href", "<p xlink:href='bla'></p>", "<p></p>" ],
|
||||
].forEach(([attr, probe, expected], index) => {
|
||||
test(t => {
|
||||
const sanitizer = new Sanitizer({allowAttributes: {[attr]: ["*"]}});
|
||||
assert_equals(sanitizer.sanitizeFor("template", probe).innerHTML,
|
||||
expected ?? probe);
|
||||
const sanitizer = new Sanitizer({allowAttributes: {[attr]: ["*"]},
|
||||
// TODO(https://github.com/WICG/sanitizer-api/issues/167)
|
||||
allowUnknownMarkup: true});
|
||||
const template = document.createElement("template");
|
||||
template.setHTML(probe, {sanitizer});
|
||||
assert_equals(template.innerHTML, expected ?? probe);
|
||||
}, `Namespaced attributes #${index}: allowAttributes: {"${attr}": ["*"]}`);
|
||||
});
|
||||
|
||||
// Most element and attribute names are lower-cased, but "foreign content"
|
||||
// like SVG and MathML have some mixed-cased names.
|
||||
[
|
||||
[ "svg:feBlend", "<feBlend></feBlend>" ],
|
||||
[ "svg:feColorMatrix", "<feColorMatrix></feColorMatrix>" ],
|
||||
[ "svg:textPath", "<textPath></textPath>" ],
|
||||
[ "feBlend", "<feBlend></feBlend>" ],
|
||||
[ "feColorMatrix", "<feColorMatrix></feColorMatrix>" ],
|
||||
[ "textPath", "<textPath></textPath>" ],
|
||||
].forEach(([elem, probe], index) => {
|
||||
const sanitize = (elem, probe) => {
|
||||
return new Sanitizer({allowElements: ["svg:svg", elem]}).
|
||||
sanitizeFor("template", `<svg>${probe}</svg`).
|
||||
content.firstElementChild.innerHTML;
|
||||
const sanitizer = new Sanitizer({allowElements: ["svg:svg", "svg:" + elem],
|
||||
// TODO(https://github.com/WICG/sanitizer-api/issues/167)
|
||||
allowUnknownMarkup: true});
|
||||
const template = document.createElement("template");
|
||||
template.setHTML(`<svg>${probe}</svg>`, {sanitizer});
|
||||
return template.content.firstElementChild.innerHTML;
|
||||
};
|
||||
test(t => {
|
||||
assert_equals(sanitize(elem, probe), probe);
|
||||
}, `Mixed-case element names #${index}: "${elem}"`);
|
||||
}, `Mixed-case element names #${index}: "svg:${elem}"`);
|
||||
test(t => {
|
||||
assert_not_equals(sanitize(elem.toLowerCase(), probe), probe);
|
||||
}, `Mixed-case element names #${index}: "${elem.toLowerCase()}"`);
|
||||
// Lowercase element names should be normalized to mixed-case.
|
||||
assert_equals(sanitize(elem.toLowerCase(), probe), probe);
|
||||
}, `Lower-case element names #${index}: "svg:${elem.toLowerCase()}"`);
|
||||
test(t => {
|
||||
assert_not_equals(sanitize(elem.toUpperCase(), probe), probe);
|
||||
}, `Mixed-case element names #${index}: "${elem.toUpperCase()}"`);
|
||||
}, `Upper-case element names #${index}: "svg:${elem.toUpperCase()}"`);
|
||||
test(t => {
|
||||
const elems = [elem];
|
||||
const elems = ["svg:" + elem];
|
||||
assert_array_equals(
|
||||
new Sanitizer({allowElements: elems}).getConfiguration().allowElements,
|
||||
elems);
|
||||
}, `Mixed case element names #${index}: "${elem}" is preserved in config.`);
|
||||
}, `Mixed case element names #${index}: "svg:${elem}" is preserved in config.`);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
Reference in New Issue
Block a user