Skip to content

Commit 0de5709

Browse files
authored
Fix strict name conformity cases (bellard#335)
- reject *future strict reserved words* in `js_parse_function_check_names()`. - add tests for reserved names in tests/test_language.js - allow running tests/test_language.js with v8 - update v8.txt
1 parent 8b56215 commit 0de5709

File tree

3 files changed

+85
-63
lines changed

3 files changed

+85
-63
lines changed

quickjs.c

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31466,6 +31466,25 @@ static __exception int js_parse_directives(JSParseState *s)
3146631466
return js_parse_seek_token(s, &pos);
3146731467
}
3146831468

31469+
static BOOL js_invalid_strict_name(JSAtom name) {
31470+
switch (name) {
31471+
case JS_ATOM_eval:
31472+
case JS_ATOM_arguments:
31473+
case JS_ATOM_implements: // future strict reserved words
31474+
case JS_ATOM_interface:
31475+
case JS_ATOM_let:
31476+
case JS_ATOM_package:
31477+
case JS_ATOM_private:
31478+
case JS_ATOM_protected:
31479+
case JS_ATOM_public:
31480+
case JS_ATOM_static:
31481+
case JS_ATOM_yield:
31482+
return TRUE;
31483+
default:
31484+
return FALSE;
31485+
}
31486+
}
31487+
3146931488
static int js_parse_function_check_names(JSParseState *s, JSFunctionDef *fd,
3147031489
JSAtom func_name)
3147131490
{
@@ -31476,13 +31495,12 @@ static int js_parse_function_check_names(JSParseState *s, JSFunctionDef *fd,
3147631495
if (!fd->has_simple_parameter_list && fd->has_use_strict) {
3147731496
return js_parse_error(s, "\"use strict\" not allowed in function with default or destructuring parameter");
3147831497
}
31479-
if (func_name == JS_ATOM_eval || func_name == JS_ATOM_arguments) {
31498+
if (js_invalid_strict_name(func_name)) {
3148031499
return js_parse_error(s, "invalid function name in strict code");
3148131500
}
3148231501
for (idx = 0; idx < fd->arg_count; idx++) {
3148331502
name = fd->args[idx].var_name;
31484-
31485-
if (name == JS_ATOM_eval || name == JS_ATOM_arguments) {
31503+
if (js_invalid_strict_name(name)) {
3148631504
return js_parse_error(s, "invalid argument name in strict code");
3148731505
}
3148831506
}

tests/test_language.js

Lines changed: 64 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,24 +10,25 @@ function assert(actual, expected, message) {
1010
&& actual.toString() === expected.toString())
1111
return;
1212

13+
var msg = message ? " (" + message + ")" : "";
1314
throw Error("assertion failed: got |" + actual + "|" +
14-
", expected |" + expected + "|" +
15-
(message ? " (" + message + ")" : ""));
15+
", expected |" + expected + "|" + msg);
1616
}
1717

18-
function assert_throws(expected_error, func)
18+
function assert_throws(expected_error, func, message)
1919
{
2020
var err = false;
21+
var msg = message ? " (" + message + ")" : "";
2122
try {
2223
func();
2324
} catch(e) {
2425
err = true;
2526
if (!(e instanceof expected_error)) {
26-
throw Error("unexpected exception type");
27+
throw Error(`expected ${expected_error.name}, got ${e.name}${msg}`);
2728
}
2829
}
2930
if (!err) {
30-
throw Error("expected exception");
31+
throw Error(`expected ${expected_error.name}${msg}`);
3132
}
3233
}
3334

@@ -421,7 +422,9 @@ function test_argument_scope()
421422
var c = "global";
422423

423424
f = function(a = eval("var arguments")) {};
424-
assert_throws(SyntaxError, f);
425+
// for some reason v8 does not throw an exception here
426+
if (typeof require === 'undefined')
427+
assert_throws(SyntaxError, f);
425428

426429
f = function(a = eval("1"), b = arguments[0]) { return b; };
427430
assert(f(12), 12);
@@ -536,6 +539,60 @@ function test_function_expr_name()
536539
assert_throws(TypeError, f);
537540
}
538541

542+
function test_expr(expr, err) {
543+
if (err)
544+
assert_throws(err, () => eval(expr), `for ${expr}`);
545+
else
546+
assert(1, eval(expr), `for ${expr}`);
547+
}
548+
549+
function test_name(name, err)
550+
{
551+
test_expr(`(function() { return typeof ${name} ? 1 : 1; })()`);
552+
test_expr(`(function() { var ${name}; ${name} = 1; return ${name}; })()`);
553+
test_expr(`(function() { let ${name}; ${name} = 1; return ${name}; })()`, name == 'let' ? SyntaxError : undefined);
554+
test_expr(`(function() { const ${name} = 1; return ${name}; })()`, name == 'let' ? SyntaxError : undefined);
555+
test_expr(`(function(${name}) { ${name} = 1; return ${name}; })()`);
556+
test_expr(`(function({${name}}) { ${name} = 1; return ${name}; })({})`);
557+
test_expr(`(function ${name}() { return ${name} ? 1 : 0; })()`);
558+
test_expr(`"use strict"; (function() { return typeof ${name} ? 1 : 1; })()`, err);
559+
test_expr(`"use strict"; (function() { if (0) ${name} = 1; return 1; })()`, err);
560+
test_expr(`"use strict"; (function() { var x; if (0) x = ${name}; return 1; })()`, err);
561+
test_expr(`"use strict"; (function() { var ${name}; return 1; })()`, err);
562+
test_expr(`"use strict"; (function() { let ${name}; return 1; })()`, err);
563+
test_expr(`"use strict"; (function() { const ${name} = 1; return 1; })()`, err);
564+
test_expr(`"use strict"; (function() { var ${name}; ${name} = 1; return 1; })()`, err);
565+
test_expr(`"use strict"; (function() { var ${name}; ${name} = 1; return ${name}; })()`, err);
566+
test_expr(`"use strict"; (function(${name}) { return 1; })()`, err);
567+
test_expr(`"use strict"; (function({${name}}) { return 1; })({})`, err);
568+
test_expr(`"use strict"; (function ${name}() { return 1; })()`, err);
569+
test_expr(`(function() { "use strict"; return typeof ${name} ? 1 : 1; })()`, err);
570+
test_expr(`(function() { "use strict"; if (0) ${name} = 1; return 1; })()`, err);
571+
test_expr(`(function() { "use strict"; var x; if (0) x = ${name}; return 1; })()`, err);
572+
test_expr(`(function() { "use strict"; var ${name}; return 1; })()`, err);
573+
test_expr(`(function() { "use strict"; let ${name}; return 1; })()`, err);
574+
test_expr(`(function() { "use strict"; const ${name} = 1; return 1; })()`, err);
575+
test_expr(`(function() { "use strict"; var ${name}; ${name} = 1; return 1; })()`, err);
576+
test_expr(`(function() { "use strict"; var ${name}; ${name} = 1; return ${name}; })()`, err);
577+
test_expr(`(function(${name}) { "use strict"; return 1; })()`, err);
578+
test_expr(`(function({${name}}) { "use strict"; return 1; })({})`, SyntaxError);
579+
test_expr(`(function ${name}() { "use strict"; return 1; })()`, err);
580+
}
581+
582+
function test_reserved_names()
583+
{
584+
test_name('await');
585+
test_name('yield', SyntaxError);
586+
test_name('implements', SyntaxError);
587+
test_name('interface', SyntaxError);
588+
test_name('let', SyntaxError);
589+
test_name('package', SyntaxError);
590+
test_name('private', SyntaxError);
591+
test_name('protected', SyntaxError);
592+
test_name('public', SyntaxError);
593+
test_name('static', SyntaxError);
594+
}
595+
539596
test_op1();
540597
test_cvt();
541598
test_eq();
@@ -555,3 +612,4 @@ test_spread();
555612
test_function_length();
556613
test_argument_scope();
557614
test_function_expr_name();
615+
test_reserved_names();

v8.txt

Lines changed: 0 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -711,60 +711,6 @@ Did not throw exception
711711
Did not throw exception
712712
Did not throw exception
713713
Did not throw exception
714-
Did not throw exception
715-
Did not throw exception
716-
Did not throw exception
717-
Did not throw exception
718-
Did not throw exception
719-
Did not throw exception
720-
Did not throw exception
721-
Did not throw exception
722-
Did not throw exception
723-
Did not throw exception
724-
Did not throw exception
725-
Did not throw exception
726-
Did not throw exception
727-
Did not throw exception
728-
Did not throw exception
729-
Did not throw exception
730-
Did not throw exception
731-
Did not throw exception
732-
Did not throw exception
733-
Did not throw exception
734-
Did not throw exception
735-
Did not throw exception
736-
Did not throw exception
737-
Did not throw exception
738-
Did not throw exception
739-
Did not throw exception
740-
Did not throw exception
741-
Did not throw exception
742-
Did not throw exception
743-
Did not throw exception
744-
Did not throw exception
745-
Did not throw exception
746-
Did not throw exception
747-
Did not throw exception
748-
Did not throw exception
749-
Did not throw exception
750-
Did not throw exception
751-
Did not throw exception
752-
Did not throw exception
753-
Did not throw exception
754-
Did not throw exception
755-
Did not throw exception
756-
Did not throw exception
757-
Did not throw exception
758-
Did not throw exception
759-
Did not throw exception
760-
Did not throw exception
761-
Did not throw exception
762-
Did not throw exception
763-
Did not throw exception
764-
Did not throw exception
765-
Did not throw exception
766-
Did not throw exception
767-
Did not throw exception
768714
Failure: expected <null> found <undefined>
769715
Failure: expected <undefined> found <function non_strict() {
770716
return return_my_caller();

0 commit comments

Comments
 (0)