Skip to content

Commit

Permalink
fix: disallow __proto__ in record
Browse files Browse the repository at this point in the history
  • Loading branch information
JLHwung committed May 31, 2020
1 parent 3a85c92 commit 42f44ea
Show file tree
Hide file tree
Showing 12 changed files with 208 additions and 7 deletions.
1 change: 1 addition & 0 deletions packages/babel-parser/src/parser/error-message.js
Expand Up @@ -126,6 +126,7 @@ export const ErrorMessages = Object.freeze({
"Record expressions starting with '{|' are only allowed when the 'syntaxType' option of the 'recordAndTuple' plugin is set to 'bar'",
RecordExpressionHashIncorrectStartSyntaxType:
"Record expressions starting with '#{' are only allowed when the 'syntaxType' option of the 'recordAndTuple' plugin is set to 'hash'",
RecordNoProto: "'__proto__' is not allowed in Record expressions",
RestTrailingComma: "Unexpected trailing comma after rest element",
SloppyFunction:
"In non-strict mode code, functions can only be declared at top level, inside a block, or as the body of an if statement",
Expand Down
18 changes: 13 additions & 5 deletions packages/babel-parser/src/parser/expression.js
Expand Up @@ -74,12 +74,15 @@ export default class ExpressionParser extends LValParser {
+takeDecorators: (node: N.HasDecorators) => void;
*/

// Check if property __proto__ has been used more than once.
// For object literal, check if property __proto__ has been used more than once.
// If the expression is a destructuring assignment, then __proto__ may appear
// multiple times. Otherwise, __proto__ is a duplicated key.

checkDuplicatedProto(
// For record expression, check if property __proto__ exists but allows "__proto__"

checkProto(
prop: N.ObjectMember | N.SpreadElement,
isRecord: boolean,
protoRef: { used: boolean },
refExpressionErrors: ?ExpressionErrors,
): void {
Expand All @@ -88,16 +91,21 @@ export default class ExpressionParser extends LValParser {
prop.type === "ObjectMethod" ||
prop.computed ||
// $FlowIgnore
prop.shorthand
(prop.shorthand && !isRecord)
) {
return;
}

const key = prop.key;
const keyIsIdentifier = key.type === "Identifier";
// It is either an Identifier or a String/NumericLiteral
const name = key.type === "Identifier" ? key.name : String(key.value);
const name = keyIsIdentifier ? key.name : key.value;

if (name === "__proto__") {
if (isRecord) {
if (keyIsIdentifier) this.raise(key.start, Errors.RecordNoProto);
return;
}
if (protoRef.used) {
if (refExpressionErrors) {
// Store the first redefinition's position, otherwise ignore because
Expand Down Expand Up @@ -1554,7 +1562,7 @@ export default class ExpressionParser extends LValParser {
const prop = this.parseObjectMember(isPattern, refExpressionErrors);
if (!isPattern) {
// $FlowIgnore RestElement will never be returned if !isPattern
this.checkDuplicatedProto(prop, propHash, refExpressionErrors);
this.checkProto(prop, isRecord, propHash, refExpressionErrors);
}

if (
Expand Down
5 changes: 3 additions & 2 deletions packages/babel-parser/src/plugins/estree.js
Expand Up @@ -143,16 +143,17 @@ export default (superClass: Class<Parser>): Class<Parser> =>
}
}

checkDuplicatedProto(
checkProto(
prop: N.ObjectMember | N.SpreadElement,
isRecord: boolean,
protoRef: { used: boolean },
refExpressionErrors: ?ExpressionErrors,
): void {
// $FlowIgnore: check prop.method and fallback to super method
if (prop.method) {
return;
}
super.checkDuplicatedProto(prop, protoRef, refExpressionErrors);
super.checkProto(prop, isRecord, protoRef, refExpressionErrors);
}

isValidDirective(stmt: N.Statement): boolean {
Expand Down
@@ -0,0 +1,3 @@
#{
__proto__: null
}
@@ -0,0 +1,3 @@
{
"plugins": [["recordAndTuple", { "syntaxType": "hash" }]]
}
@@ -0,0 +1,42 @@
{
"type": "File",
"start":0,"end":22,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
"errors": [
"SyntaxError: '__proto__' is not allowed in Record expressions (2:2)"
],
"program": {
"type": "Program",
"start":0,"end":22,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start":0,"end":22,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
"expression": {
"type": "RecordExpression",
"start":0,"end":22,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
"properties": [
{
"type": "ObjectProperty",
"start":5,"end":20,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":17}},
"method": false,
"key": {
"type": "Identifier",
"start":5,"end":14,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":11},"identifierName":"__proto__"},
"name": "__proto__"
},
"computed": false,
"shorthand": false,
"value": {
"type": "NullLiteral",
"start":16,"end":20,"loc":{"start":{"line":2,"column":13},"end":{"line":2,"column":17}}
}
}
]
}
}
],
"directives": []
}
}
@@ -0,0 +1,4 @@
var __proto__;
#{
__proto__
}
@@ -0,0 +1,3 @@
{
"plugins": [["recordAndTuple", { "syntaxType": "hash" }]]
}
@@ -0,0 +1,63 @@
{
"type": "File",
"start":0,"end":31,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":1}},
"errors": [
"SyntaxError: '__proto__' is not allowed in Record expressions (3:2)"
],
"program": {
"type": "Program",
"start":0,"end":31,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":1}},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "VariableDeclaration",
"start":0,"end":14,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":14}},
"declarations": [
{
"type": "VariableDeclarator",
"start":4,"end":13,"loc":{"start":{"line":1,"column":4},"end":{"line":1,"column":13}},
"id": {
"type": "Identifier",
"start":4,"end":13,"loc":{"start":{"line":1,"column":4},"end":{"line":1,"column":13},"identifierName":"__proto__"},
"name": "__proto__"
},
"init": null
}
],
"kind": "var"
},
{
"type": "ExpressionStatement",
"start":15,"end":31,"loc":{"start":{"line":2,"column":0},"end":{"line":4,"column":1}},
"expression": {
"type": "RecordExpression",
"start":15,"end":31,"loc":{"start":{"line":2,"column":0},"end":{"line":4,"column":1}},
"properties": [
{
"type": "ObjectProperty",
"start":20,"end":29,"loc":{"start":{"line":3,"column":2},"end":{"line":3,"column":11}},
"method": false,
"key": {
"type": "Identifier",
"start":20,"end":29,"loc":{"start":{"line":3,"column":2},"end":{"line":3,"column":11},"identifierName":"__proto__"},
"name": "__proto__"
},
"computed": false,
"shorthand": true,
"value": {
"type": "Identifier",
"start":20,"end":29,"loc":{"start":{"line":3,"column":2},"end":{"line":3,"column":11},"identifierName":"__proto__"},
"name": "__proto__"
},
"extra": {
"shorthand": true
}
}
]
}
}
],
"directives": []
}
}
@@ -0,0 +1,4 @@
#{
"__proto__": null,
"__proto__": null,
}
@@ -0,0 +1,3 @@
{
"plugins": [["recordAndTuple", { "syntaxType": "hash" }]]
}
@@ -0,0 +1,66 @@
{
"type": "File",
"start":0,"end":46,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":1}},
"program": {
"type": "Program",
"start":0,"end":46,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":1}},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start":0,"end":46,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":1}},
"expression": {
"type": "RecordExpression",
"start":0,"end":46,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":1}},
"properties": [
{
"type": "ObjectProperty",
"start":5,"end":22,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":19}},
"method": false,
"key": {
"type": "StringLiteral",
"start":5,"end":16,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":13}},
"extra": {
"rawValue": "__proto__",
"raw": "\"__proto__\""
},
"value": "__proto__"
},
"computed": false,
"shorthand": false,
"value": {
"type": "NullLiteral",
"start":18,"end":22,"loc":{"start":{"line":2,"column":15},"end":{"line":2,"column":19}}
}
},
{
"type": "ObjectProperty",
"start":26,"end":43,"loc":{"start":{"line":3,"column":2},"end":{"line":3,"column":19}},
"method": false,
"key": {
"type": "StringLiteral",
"start":26,"end":37,"loc":{"start":{"line":3,"column":2},"end":{"line":3,"column":13}},
"extra": {
"rawValue": "__proto__",
"raw": "\"__proto__\""
},
"value": "__proto__"
},
"computed": false,
"shorthand": false,
"value": {
"type": "NullLiteral",
"start":39,"end":43,"loc":{"start":{"line":3,"column":15},"end":{"line":3,"column":19}}
}
}
],
"extra": {
"trailingComma": 43
}
}
}
],
"directives": []
}
}

0 comments on commit 42f44ea

Please sign in to comment.