Skip to content

Commit

Permalink
Remove length restriction from JSX entities, and ignore `Object.proto…
Browse files Browse the repository at this point in the history
…type` (#14327)

* Allow any length in unicode CP jsx entities

* Add failing test

* Don't access entities from Object.prototype

* Add `&#0_0;` test

* Fix `�` parsing
  • Loading branch information
nicolo-ribaudo committed Mar 6, 2022
1 parent 5cf3118 commit 4bb9b89
Show file tree
Hide file tree
Showing 11 changed files with 272 additions and 35 deletions.
76 changes: 44 additions & 32 deletions packages/babel-parser/src/plugins/jsx/index.js
Expand Up @@ -22,9 +22,6 @@ import type { Position } from "../../util/location";
import { isNewLine } from "../../util/whitespace";
import { Errors, makeErrorTemplates, ErrorCodes } from "../../parser/error";

const HEX_NUMBER = /^[\da-fA-F]+$/;
const DECIMAL_NUMBER = /^\d+$/;

/* eslint sort-keys: "error" */
const JsxErrors = makeErrorTemplates(
{
Expand Down Expand Up @@ -190,39 +187,54 @@ export default (superClass: Class<Parser>): Class<Parser> =>
}

jsxReadEntity(): string {
let str = "";
let count = 0;
let entity;
let ch = this.input[this.state.pos];

const startPos = ++this.state.pos;
while (this.state.pos < this.length && count++ < 10) {
ch = this.input[this.state.pos++];
if (ch === ";") {
if (str[0] === "#") {
if (str[1] === "x") {
str = str.substr(2);
if (HEX_NUMBER.test(str)) {
entity = String.fromCodePoint(parseInt(str, 16));
}
} else {
str = str.substr(1);
if (DECIMAL_NUMBER.test(str)) {
entity = String.fromCodePoint(parseInt(str, 10));
}
}
} else {
entity = XHTMLEntities[str];
if (this.codePointAtPos(this.state.pos) === charCodes.numberSign) {
++this.state.pos;

let radix = 10;
if (this.codePointAtPos(this.state.pos) === charCodes.lowercaseX) {
radix = 16;
++this.state.pos;
}

const codePoint = this.readInt(
radix,
/* len */ undefined,
/* forceLen */ false,
/* allowNumSeparator */ "bail",
);
if (
codePoint !== null &&
this.codePointAtPos(this.state.pos) === charCodes.semicolon
) {
++this.state.pos;
return String.fromCodePoint(codePoint);
}
} else {
let count = 0;
let semi = false;
while (
count++ < 10 &&
this.state.pos < this.length &&
!(semi = this.codePointAtPos(this.state.pos) == charCodes.semicolon)
) {
++this.state.pos;
}

if (semi) {
const desc = this.input.slice(startPos, this.state.pos);
const entity = XHTMLEntities[desc];
++this.state.pos;

if (entity) {
return entity;
}
break;
}
str += ch;
}
if (!entity) {
this.state.pos = startPos;
return "&";
}
return entity;

// Not a valid entity
this.state.pos = startPos;
return "&";
}

// Read a JSX identifier (valid tag or attribute name).
Expand Down
3 changes: 2 additions & 1 deletion packages/babel-parser/src/plugins/jsx/xhtml.js
@@ -1,6 +1,7 @@
// @flow

const entities: { [name: string]: string } = {
const entities: { [name: string]: string, __proto__: null } = {
__proto__: null,
quot: "\u0022",
amp: "&",
apos: "\u0027",
Expand Down
4 changes: 2 additions & 2 deletions packages/babel-parser/src/tokenizer/index.js
Expand Up @@ -1174,7 +1174,7 @@ export default class Tokenizer extends ParserErrors {
radix: number,
len?: number,
forceLen?: boolean,
allowNumSeparator: boolean = true,
allowNumSeparator: boolean | "bail" = true,
): number | null {
const start = this.state.pos;
const forbiddenSiblings =
Expand All @@ -1197,7 +1197,7 @@ export default class Tokenizer extends ParserErrors {
const code = this.input.charCodeAt(this.state.pos);
let val;
if (code === charCodes.underscore) {
if (code === charCodes.underscore && allowNumSeparator !== "bail") {
const prev = this.input.charCodeAt(this.state.pos - 1);
const next = this.input.charCodeAt(this.state.pos + 1);
if (allowedSiblings.indexOf(next) === -1) {
Expand Down
@@ -0,0 +1,7 @@
<a>
&#1234;
&#xABC;
&#00000000000000000000001234;
&#x0000000000000000000000ABC;
&#0000;
</a>
@@ -0,0 +1,52 @@
{
"type": "File",
"start":0,"end":112,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":7,"column":4,"index":112}},
"program": {
"type": "Program",
"start":0,"end":112,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":7,"column":4,"index":112}},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start":0,"end":112,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":7,"column":4,"index":112}},
"expression": {
"type": "JSXElement",
"start":0,"end":112,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":7,"column":4,"index":112}},
"openingElement": {
"type": "JSXOpeningElement",
"start":0,"end":3,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":3,"index":3}},
"name": {
"type": "JSXIdentifier",
"start":1,"end":2,"loc":{"start":{"line":1,"column":1,"index":1},"end":{"line":1,"column":2,"index":2}},
"name": "a"
},
"attributes": [],
"selfClosing": false
},
"closingElement": {
"type": "JSXClosingElement",
"start":108,"end":112,"loc":{"start":{"line":7,"column":0,"index":108},"end":{"line":7,"column":4,"index":112}},
"name": {
"type": "JSXIdentifier",
"start":110,"end":111,"loc":{"start":{"line":7,"column":2,"index":110},"end":{"line":7,"column":3,"index":111}},
"name": "a"
}
},
"children": [
{
"type": "JSXText",
"start":3,"end":108,"loc":{"start":{"line":1,"column":3,"index":3},"end":{"line":7,"column":0,"index":108}},
"extra": {
"rawValue": "\n Ӓ\n\n Ӓ\n\n \u0000\n",
"raw": "\n &#1234;\n &#xABC;\n &#00000000000000000000001234;\n &#x0000000000000000000000ABC;\n &#0000;\n"
},
"value": "\n Ӓ\n\n Ӓ\n\n \u0000\n"
}
]
}
}
],
"directives": []
}
}
@@ -0,0 +1 @@
<a>&amp;</a>
@@ -0,0 +1,52 @@
{
"type": "File",
"start":0,"end":12,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":12,"index":12}},
"program": {
"type": "Program",
"start":0,"end":12,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":12,"index":12}},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start":0,"end":12,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":12,"index":12}},
"expression": {
"type": "JSXElement",
"start":0,"end":12,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":12,"index":12}},
"openingElement": {
"type": "JSXOpeningElement",
"start":0,"end":3,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":3,"index":3}},
"name": {
"type": "JSXIdentifier",
"start":1,"end":2,"loc":{"start":{"line":1,"column":1,"index":1},"end":{"line":1,"column":2,"index":2}},
"name": "a"
},
"attributes": [],
"selfClosing": false
},
"closingElement": {
"type": "JSXClosingElement",
"start":8,"end":12,"loc":{"start":{"line":1,"column":8,"index":8},"end":{"line":1,"column":12,"index":12}},
"name": {
"type": "JSXIdentifier",
"start":10,"end":11,"loc":{"start":{"line":1,"column":10,"index":10},"end":{"line":1,"column":11,"index":11}},
"name": "a"
}
},
"children": [
{
"type": "JSXText",
"start":3,"end":8,"loc":{"start":{"line":1,"column":3,"index":3},"end":{"line":1,"column":8,"index":8}},
"extra": {
"rawValue": "&",
"raw": "&amp;"
},
"value": "&"
}
]
}
}
],
"directives": []
}
}
@@ -0,0 +1,7 @@
<a>
&amp
&ampa;
&amp ;
&xamp;
&#0_0;
</a>
@@ -0,0 +1,52 @@
{
"type": "File",
"start":0,"end":61,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":7,"column":4,"index":61}},
"program": {
"type": "Program",
"start":0,"end":61,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":7,"column":4,"index":61}},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start":0,"end":61,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":7,"column":4,"index":61}},
"expression": {
"type": "JSXElement",
"start":0,"end":61,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":7,"column":4,"index":61}},
"openingElement": {
"type": "JSXOpeningElement",
"start":0,"end":3,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":3,"index":3}},
"name": {
"type": "JSXIdentifier",
"start":1,"end":2,"loc":{"start":{"line":1,"column":1,"index":1},"end":{"line":1,"column":2,"index":2}},
"name": "a"
},
"attributes": [],
"selfClosing": false
},
"closingElement": {
"type": "JSXClosingElement",
"start":57,"end":61,"loc":{"start":{"line":7,"column":0,"index":57},"end":{"line":7,"column":4,"index":61}},
"name": {
"type": "JSXIdentifier",
"start":59,"end":60,"loc":{"start":{"line":7,"column":2,"index":59},"end":{"line":7,"column":3,"index":60}},
"name": "a"
}
},
"children": [
{
"type": "JSXText",
"start":3,"end":57,"loc":{"start":{"line":1,"column":3,"index":3},"end":{"line":7,"column":0,"index":57}},
"extra": {
"rawValue": "\n &amp\n &ampa;\n &amp ;\n &xamp;\n &#0_0;\n",
"raw": "\n &amp\n &ampa;\n &amp ;\n &xamp;\n &#0_0;\n"
},
"value": "\n &amp\n &ampa;\n &amp ;\n &xamp;\n &#0_0;\n"
}
]
}
}
],
"directives": []
}
}
@@ -0,0 +1 @@
<a>&valueOf;</a>
@@ -0,0 +1,52 @@
{
"type": "File",
"start":0,"end":16,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":16,"index":16}},
"program": {
"type": "Program",
"start":0,"end":16,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":16,"index":16}},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start":0,"end":16,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":16,"index":16}},
"expression": {
"type": "JSXElement",
"start":0,"end":16,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":16,"index":16}},
"openingElement": {
"type": "JSXOpeningElement",
"start":0,"end":3,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":3,"index":3}},
"name": {
"type": "JSXIdentifier",
"start":1,"end":2,"loc":{"start":{"line":1,"column":1,"index":1},"end":{"line":1,"column":2,"index":2}},
"name": "a"
},
"attributes": [],
"selfClosing": false
},
"closingElement": {
"type": "JSXClosingElement",
"start":12,"end":16,"loc":{"start":{"line":1,"column":12,"index":12},"end":{"line":1,"column":16,"index":16}},
"name": {
"type": "JSXIdentifier",
"start":14,"end":15,"loc":{"start":{"line":1,"column":14,"index":14},"end":{"line":1,"column":15,"index":15}},
"name": "a"
}
},
"children": [
{
"type": "JSXText",
"start":3,"end":12,"loc":{"start":{"line":1,"column":3,"index":3},"end":{"line":1,"column":12,"index":12}},
"extra": {
"rawValue": "&valueOf;",
"raw": "&valueOf;"
},
"value": "&valueOf;"
}
]
}
}
],
"directives": []
}
}

0 comments on commit 4bb9b89

Please sign in to comment.