Skip to content

Commit

Permalink
fix(parser): fixed eval and arguments validations
Browse files Browse the repository at this point in the history
  • Loading branch information
KFlash committed Jul 28, 2019
1 parent a98ead0 commit 1a927be
Show file tree
Hide file tree
Showing 13 changed files with 245 additions and 84 deletions.
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "meriyah",
"version": "1.4.5",
"version": "1.4.6",
"description": "A 100% compliant, self-hosted javascript parser with high focus on both performance and stability",
"main": "dist/meriyah.umd.js",
"module": "dist/meriyah.esm.js",
Expand Down
2 changes: 1 addition & 1 deletion src/meriyah.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@ export function parse(source: string, options?: Options): ESTree.Program {
export { ESTree, Options };

// Export current version
export const version = '1.4.5';
export const version = '1.4.6';
86 changes: 37 additions & 49 deletions src/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1053,8 +1053,9 @@ export function parseAsyncArrowOrAsyncFunctionDeclaration(
report(parser, Errors.YieldInParameter);
}

if ((parser.token & Token.IsEvalOrArguments) === Token.IsEvalOrArguments)
parser.flags |= Flags.StrictEvalArguments;
if ((parser.token & Token.IsEvalOrArguments) === Token.IsEvalOrArguments) {
parser.flags |= Flags.SimpleParameterList;
}

if (scope) {
scope = addChildScope(createScope(), ScopeKind.FuncBody);
Expand Down Expand Up @@ -3476,31 +3477,24 @@ export function parseFunctionBody(
}
body.push(parseDirective(parser, context, expr, token, tokenPos, parser.linePos, parser.colPos));
}
if (
context & Context.Strict &&
firstRestricted &&
((firstRestricted & Token.IsEvalOrArguments) === Token.IsEvalOrArguments ||
(firstRestricted & Token.FutureReserved) === Token.FutureReserved)
) {
report(parser, Errors.StrictFunctionName);
}

if (context & Context.Strict) {
if (
scope &&
(scopeError !== void 0 && (prevContext & Context.Strict) < 1 && (context & Context.InGlobal) === 0)
) {
reportScopeError(scopeError);
}

if (parser.flags & Flags.HasStrictReserved) report(parser, Errors.UnexpectedStrictReserved);
if (parser.flags & Flags.StrictEvalArguments) report(parser, Errors.StrictEvalArguments);
if (
firstRestricted &&
((firstRestricted & Token.IsEvalOrArguments) === Token.IsEvalOrArguments ||
(firstRestricted & Token.FutureReserved) === Token.FutureReserved)
) {
report(parser, Errors.StrictFunctionName);
}
if (
context & Context.OptionsLexical &&
scope &&
(scopeError !== void 0 && (prevContext & Context.Strict) < 1 && (context & Context.InGlobal) === 0)
) {
reportScopeError(scopeError);
}
}

parser.flags =
(parser.flags | Flags.HasStrictReserved | Flags.StrictEvalArguments) ^
(Flags.StrictEvalArguments | Flags.HasStrictReserved);

while (parser.token !== Token.RightBrace) {
body.push(parseStatementListItem(
parser,
Expand Down Expand Up @@ -3890,7 +3884,9 @@ export function parsePrimaryExpressionExtended(
parser.flags = (parser.flags | Flags.SimpleParameterList) ^ Flags.SimpleParameterList;
if (IsEvalOrArguments) {
if (context & Context.Strict) report(parser, Errors.StrictEvalArguments);
parser.flags |= Flags.StrictEvalArguments;
parser.flags |= Flags.SimpleParameterList;
} else {
parser.flags &= ~Flags.SimpleParameterList;
}

if (!allowAssign) report(parser, Errors.InvalidAssignmentTarget);
Expand Down Expand Up @@ -6259,7 +6255,7 @@ export function parseMethodFormals(
((parser.token & Token.FutureReserved) === Token.FutureReserved ||
(parser.token & Token.IsEvalOrArguments) === Token.IsEvalOrArguments)
) {
parser.flags |= Flags.StrictEvalArguments;
parser.flags |= Flags.SimpleParameterList;
}

if (scope && (parser.token & Token.IsIdentifier) === Token.IsIdentifier) {
Expand Down Expand Up @@ -6445,16 +6441,12 @@ export function parseParenthesizedExpression(
if (parser.assignable & AssignmentKind.NotAssignable) {
destructible |= DestructuringKind.CannotDestruct;
isComplex = 1;
} else if ((token & Token.IsEvalOrArguments) === Token.IsEvalOrArguments) {
parser.flags |= Flags.StrictEvalArguments;
} else if (
(token & Token.IsEvalOrArguments) === Token.IsEvalOrArguments ||
(token & Token.FutureReserved) === Token.FutureReserved
) {
isComplex = 1;
}

parser.flags |=
(token & Token.IsEvalOrArguments) === Token.IsEvalOrArguments
? Flags.StrictEvalArguments
: (token & Token.FutureReserved) === Token.FutureReserved
? Flags.HasStrictReserved
: 0;
} else {
if (parser.token === Token.Assign) {
isComplex = 1;
Expand Down Expand Up @@ -6806,15 +6798,13 @@ export function parseFormalParametersOrFormalList(
let left: any;
const { tokenPos, tokenValue, linePos, colPos } = parser;
if (parser.token & Token.IsIdentifier) {
if ((context & Context.Strict) === 0) {
if ((parser.token & Token.IsEvalOrArguments) === Token.IsEvalOrArguments) {
parser.flags |= Flags.StrictEvalArguments;
}
if ((parser.token & Token.FutureReserved) === Token.FutureReserved) {
parser.flags |= Flags.HasStrictReserved;
}
if (
(context & Context.Strict) === 0 &&
((parser.token & Token.FutureReserved) === Token.FutureReserved ||
(parser.token & Token.IsEvalOrArguments) === Token.IsEvalOrArguments)
) {
isComplex = 1;
}

if (scope) {
// Strict-mode disallows duplicate args. We may not know whether we are
// in strict mode or not (since the function body hasn't been parsed).
Expand Down Expand Up @@ -7264,14 +7254,12 @@ export function parseAsyncArrowOrCallExpression(
if (parser.assignable & AssignmentKind.NotAssignable) {
destructible |= DestructuringKind.CannotDestruct;
isComplex = 1;
} else if (
(token & Token.IsEvalOrArguments) === Token.IsEvalOrArguments ||
(token & Token.FutureReserved) === Token.FutureReserved
) {
isComplex = 1;
}

parser.flags |=
(token & Token.IsEvalOrArguments) === Token.IsEvalOrArguments
? Flags.StrictEvalArguments
: (token & Token.FutureReserved) === Token.FutureReserved
? Flags.HasStrictReserved
: 0;
} else {
if (parser.token === Token.Assign) {
isComplex = 1;
Expand Down
35 changes: 22 additions & 13 deletions test/parser/declarations/async-function.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,19 @@ describe('Declarations - Async Function', () => {
'async function * f() { for await ({a: a} of []); }',
'async function * f() { for await ({0: a} of []); }',
'async function * f() { for await ({0: a = 1} of []); }',
'async function f3({x}) { var y = x; var x = 2; return y; }',
'async function f4({x}) { { var y = x; var x = 2; } return y; }',
'async function f6({x}, g = () => x) { { var x = 2; } return g(); }',
'async function f7({x}) { var g = () => x; var x = 2; return g(); }',
'async function f8({x}) { { var g = () => x; var x = 2; } return g(); }',
'async function f9({x}, g = () => eval("x")) { var x = 2; return g(); }',
'async function f12(y, g = () => y) { var y = 2; return g(); }',
'async function f11({x}, y) { var z = y; var y = 2; return z; }',
'async function f13({x}, y, [z], v) { var x, y, z; return x*y*z*v }',
'async function f20({x}) { function x() { return 2 }; return x(); }',
'async function f1(x = (y = 1)) { z = 1; await undefined; w = 1; };',
'async function f1(a, b, c) { await a; }',
'async function f1({x}) { var x = 2; return x }',
'async function x({x}) { var y = x; var x = 2; return y; }',
'async function x({x}) { { var y = x; var x = 2; } return y; }',
'async function x({x}, g = () => x) { { var x = 2; } return g(); }',
'async function x({x}) { var g = () => x; var x = 2; return g(); }',
'async function x({x}) { { var g = () => x; var x = 2; } return g(); }',
'async function x({x}, g = () => eval("x")) { var x = 2; return g(); }',
'async function x(y, g = () => y) { var y = 2; return g(); }',
'async function x({x}, y) { var z = y; var y = 2; return z; }',
'async function x({x}, y, [z], v) { var x, y, z; return x*y*z*v }',
'async function x({x}) { function x() { return 2 }; return x(); }',
'async function x(x = (y = 1)) { z = 1; await undefined; w = 1; };',
'async function x(a, b, c) { await a; }',
'async function a({x}) { var x = 2; return x }',
'async function a() { await 4; } var await = 5',
'async function a() { function b() { return await; } }',
'async function a() { var k = { async: 4 } }',
Expand Down Expand Up @@ -430,6 +430,15 @@ describe('Declarations - Async Function', () => {
['async function* f() { a = async function*(a = await) {}; }', Context.None],
['function f(a = async function(a = await) {}) {}', Context.None],
['({async\nfoo() { }})', Context.None],
[
`async function x(a=class b{
[a = class b{
[await 0](){}
}](){}
}) {
}`,
Context.None
],
['({async get foo() { }})', Context.None],
['({async set foo(value) { }})', Context.None],
['({async foo() { var await }})', Context.None],
Expand Down
84 changes: 84 additions & 0 deletions test/parser/declarations/functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ describe('Declarations - Function', () => {
['function test({...[]}) {}', Context.None],
['function test({...x = 1}) {}', Context.None],
['function test({...{}}) {}', Context.None],
['function w(casecase){y:j:function casecase(){}}', Context.None],
['function test({...x = 1}) {}', Context.None],
['function foo() { "use strict"; 00004; }', Context.Strict],
['function foo() { 00004; }', Context.Strict],
Expand Down Expand Up @@ -556,6 +557,7 @@ describe('Declarations - Function', () => {
'function *f(){ class x { [yield y](){} } }',
'function *f(){ class x { [yield](){} } }',
'function *f(){ class x { yield(){} } }',
'function f() { throw `${delete(y)}`; }',
'async function* a() { for (let m in ((yield))) x; (r = a) => {} }'
]) {
it(`${arg}`, () => {
Expand All @@ -572,6 +574,88 @@ describe('Declarations - Function', () => {
}

pass('Declarations - Function (pass)', [
[
'function w(casecase){y:j:function casecase(){}}',
Context.OptionsWebCompat | Context.OptionsRanges,
{
type: 'Program',
sourceType: 'script',
body: [
{
type: 'FunctionDeclaration',
params: [
{
type: 'Identifier',
name: 'casecase',
start: 11,
end: 19
}
],
body: {
type: 'BlockStatement',
body: [
{
type: 'LabeledStatement',
label: {
type: 'Identifier',
name: 'y',
start: 21,
end: 22
},
body: {
type: 'LabeledStatement',
label: {
type: 'Identifier',
name: 'j',
start: 23,
end: 24
},
body: {
type: 'FunctionDeclaration',
params: [],
body: {
type: 'BlockStatement',
body: [],
start: 44,
end: 46
},
async: false,
generator: false,
id: {
type: 'Identifier',
name: 'casecase',
start: 34,
end: 42
},
start: 25,
end: 46
},
start: 23,
end: 46
},
start: 21,
end: 46
}
],
start: 20,
end: 47
},
async: false,
generator: false,
id: {
type: 'Identifier',
name: 'w',
start: 9,
end: 10
},
start: 0,
end: 47
}
],
start: 0,
end: 47
}
],
[
'function* x() { for (const [j = yield] in (x) => {}) {} }',
Context.None,
Expand Down
2 changes: 2 additions & 0 deletions test/parser/expressions/unary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ describe('Expressions - Unary', () => {
'typeof x === "undefined"',
'delete o["y"]',
'delete Number(7)',
'delete ((x) => x)',
'delete ((x) => x).foo',
'delete new Number(8)',
'delete a[2]',
'delete o[Math.pow(2,30)]'
Expand Down
9 changes: 9 additions & 0 deletions test/parser/miscellaneous/grammar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,13 @@ describe('Miscellaneous - Cover grammar', () => {
parseSource(fn(`...{`), undefined, Context.OptionsWebCompat);
});
});
/*
it(fn(`...[p.q]`), () => {
t.throws(() => {
parseSource(fn(`...[p.q]`), undefined, Context.OptionsWebCompat);
});
});
*/

it(fn(`...[0]`), () => {
t.throws(() => {
Expand Down Expand Up @@ -3104,6 +3111,8 @@ describe('Miscellaneous - Cover grammar', () => {
'f = async function* g([_, x]) {}',
'f = async function* g([{ u: v, w: x, y: z } = { u: 444, w: 555, y: 666 }]) {}',
'f = async function* g([, , ...x]) {}',
'[(x) = y] = z',
'[(x) = y]',
'f = async function* g([[] = function() { initCount += 1; }()] = [[23]]) {}',
'var C = class { static async *method({ w: [x, y, z] = [4, 5, 6] }) {}}',
'class C { async *method([x, y, z] = [1, 2, 3]) {}}',
Expand Down
19 changes: 19 additions & 0 deletions test/parser/miscellaneous/pass.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ describe('Miscellaneous - Pass', () => {
`do throw function(){}
while(y)
for(;;)x`,
`function runNearStackLimit(f) { function t() { try { t(); } catch(e) { f(); } }; try { t(); } catch(e) {} }
function quit() {}
function nop() {}
try { gc; } catch(e) { gc = nop; }`,
`a = let\n{}`,
`throw(protected(x=>{"use strict"}))`,
`for ({da = 2e308} of ([, , , (arguments[((f))]).break = (null)] = (/(?=\B\b)/gmuy === njbcpwhomopc.switch))) continue`,
`for (var c, f; (/[+-\\l-]/u); ((class {}).with)) var i;`,
Expand Down Expand Up @@ -10047,6 +10052,20 @@ var func2 = function(argMath100,...argArr101){
var reResult0='%$'+'º{'+'%Ã' + 'ûÛ'.search(/(?=\B.)/imy);
return (typeof(((strvar7).replace(/a/g, ('È').replace('È', 'Ã!'+'qÄ'+'U*' + 'é%'))).replace((strvar7).replace(/a/g, ('È').replace('È', 'Ã!'+'qÄ'+'U*' + 'é%')), strvar6)) == 'boolean') ;
};`,
`function* qegv() {
;(null);
debugger
let [] = (((yield* ((yield)))));
do debugger; while ((null))
}
for (new ((dieqffaqtlfrca = ((((true))).yield **= ((eval)))))(((new (((++(/M^\u4afE\ufDeB$/gm).y)))((jetkknpsm))))).void in (rlil = ((false.prototype)))) var [...[]] = (((""))), sdsukajfdph, kgiujhouegnpnm = function pjsoeexyswiv([], ...{}) {
for (;;) ;
{}
for (var q of ((/\\B/gim))) ;
}, [i, , , ...{}] = (({[((5192))]() {
"use strict"
}, eval, [/\u1312+?/mu]: (2e308), set [(2e308)] ([]) {
}}));`,
`var func3 = function(argMath113,argMath114,argMath115,argMath116 = (argMath115 + argMath113)){
if((func2.call(arrObj0 , strvar1, ary) && (~ -2147483648))) {
}
Expand Down

0 comments on commit 1a927be

Please sign in to comment.