Merge pull request #21682 from calixteman/fix/xml-invalid-char-ref

Don't throw on an invalid XML character reference
This commit is contained in:
Tim van der Meij 2026-08-02 12:26:49 +02:00 committed by GitHub
commit 5dc1d0c5d5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 27 additions and 6 deletions

View File

@ -53,12 +53,12 @@ class XMLParserBase {
}
_resolveEntities(s) {
return s.replaceAll(XMLParserBase._entityRegex, (_, hex, dec, entity) => {
if (hex) {
return String.fromCodePoint(parseInt(hex, 16));
}
if (dec) {
return String.fromCodePoint(parseInt(dec, 10));
return s.replaceAll(XMLParserBase._entityRegex, (all, hex, dec, entity) => {
if (hex || dec) {
const code = hex ? parseInt(hex, 16) : parseInt(dec, 10);
// An out-of-range or unparsable code point is kept as-is, since
// `String.fromCodePoint` would throw on it.
return code >= 0 && code <= 0x10ffff ? String.fromCodePoint(code) : all;
}
switch (entity) {
case "lt":

View File

@ -109,6 +109,27 @@ describe("XML", function () {
});
});
describe("character references", function () {
const parseText = xml =>
new SimpleXMLParser({}).parseFromString(xml).documentElement.textContent;
it("should resolve the valid ones", function () {
expect(parseText("<a>&#65;&#x42;&#x1F602;&#0;&#x10FFFF;</a>")).toEqual(
"AB\u{1F602}\0\u{10FFFF}"
);
});
it("should keep the invalid ones as-is", function () {
// These must not throw: `String.fromCodePoint` rejects anything which
// isn't a code point.
expect(parseText("<a>&#xZZ;</a>")).toEqual("&#xZZ;");
expect(parseText("<a>&#zz;</a>")).toEqual("&#zz;");
expect(parseText("<a>&#x110000;</a>")).toEqual("&#x110000;");
expect(parseText("<a>&#1114112;</a>")).toEqual("&#1114112;");
expect(parseText("<a>&#-1;</a>")).toEqual("&#-1;");
});
});
it("should parse processing instructions", function () {
const xml = `
<a>