Commit fc1b3f8f authored by oliver@apple.com's avatar oliver@apple.com
Browse files

2011-01-16 Oliver Hunt <oliver@apple.com>

        Reviewed by Geoffrey Garen.

        Strict mode restrictions on arguments and eval usage aren't complete
        https://bugs.webkit.org/show_bug.cgi?id=52528

        Add a helper function to aid parse failure tests by testing both direct
        eval/global code, and nested code (so that we test the syntax checker
        mode as well)

        * fast/js/basic-strict-mode-expected.txt:
        * fast/js/script-tests/basic-strict-mode.js:
        (shouldBeSyntaxError):
2011-01-16  Oliver Hunt  <oliver@apple.com>

        Reviewed by Geoffrey Garen.

        Strict mode restrictions on arguments and eval usage aren't complete
        https://bugs.webkit.org/show_bug.cgi?id=52528

        Fix a few bugs in strict mode where we incorrect allow mutation of
        arguments and eval in the parser.

        Alas the "optimisation" used by the syntax checker for validating
        binary and unary expressions was too aggressive: we do actually need
        a stack for operations and operands although it needn't be as complete
        as that used for the full AST builder.

        Also disallow assignment to arguments in all cases as allowing arguments
        to be assignable is always an error in strict mode, regardless of context.

        * parser/ASTBuilder.h:
        (JSC::ASTBuilder::BinaryExprContext::BinaryExprContext):
        (JSC::ASTBuilder::UnaryExprContext::UnaryExprContext):
        * parser/JSParser.cpp:
        (JSC::JSParser::parseAssignmentExpression):
        (JSC::JSParser::parseBinaryExpression):
        (JSC::JSParser::parseUnaryExpression):
        * parser/SyntaxChecker.h:
        (JSC::SyntaxChecker::BinaryExprContext::BinaryExprContext):
        (JSC::SyntaxChecker::BinaryExprContext::~BinaryExprContext):
        (JSC::SyntaxChecker::UnaryExprContext::UnaryExprContext):
        (JSC::SyntaxChecker::UnaryExprContext::~UnaryExprContext):
        (JSC::SyntaxChecker::appendBinaryExpressionInfo):
        (JSC::SyntaxChecker::operatorStackPop):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@75896 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent b8633a7b
2011-01-16 Oliver Hunt <oliver@apple.com>
Reviewed by Geoffrey Garen.
Strict mode restrictions on arguments and eval usage aren't complete
https://bugs.webkit.org/show_bug.cgi?id=52528
Add a helper function to aid parse failure tests by testing both direct
eval/global code, and nested code (so that we test the syntax checker
mode as well)
* fast/js/basic-strict-mode-expected.txt:
* fast/js/script-tests/basic-strict-mode.js:
(shouldBeSyntaxError):
2011-01-16 Robert Hogan <robert@webkit.org>
 
Unreviewed, re-skip test after r75894.
......
......@@ -29,18 +29,31 @@ PASS testThis.apply() is undefined
PASS testThis.call(undefined) is undefined
PASS testThis.apply(undefined) is undefined
PASS (function eval(){'use strict';}) threw exception SyntaxError: Parse error.
PASS (function(){(function eval(){'use strict';})}) threw exception SyntaxError: Parse error.
PASS (function (eval){'use strict';}) threw exception SyntaxError: Parse error.
PASS (function(){(function (eval){'use strict';})}) threw exception SyntaxError: Parse error.
PASS (function arguments(){'use strict';}) threw exception SyntaxError: Parse error.
PASS (function(){(function arguments(){'use strict';})}) threw exception SyntaxError: Parse error.
PASS (function (arguments){'use strict';}) threw exception SyntaxError: Parse error.
PASS (function(){(function (arguments){'use strict';})}) threw exception SyntaxError: Parse error.
PASS (function (){'use strict'; var eval;}) threw exception SyntaxError: Parse error.
PASS (function(){(function (){'use strict'; var eval;})}) threw exception SyntaxError: Parse error.
PASS (function (){'use strict'; var arguments;}) threw exception SyntaxError: Parse error.
PASS (function(){(function (){'use strict'; var arguments;})}) threw exception SyntaxError: Parse error.
PASS (function (){'use strict'; try{}catch(eval){}}) threw exception SyntaxError: Parse error.
PASS (function(){(function (){'use strict'; try{}catch(eval){}})}) threw exception SyntaxError: Parse error.
PASS (function (){'use strict'; try{}catch(arguments){}}) threw exception SyntaxError: Parse error.
PASS (function(){(function (){'use strict'; try{}catch(arguments){}})}) threw exception SyntaxError: Parse error.
PASS (function (a, a){'use strict';}) threw exception SyntaxError: Parse error.
PASS (function(){(function (a, a){'use strict';})}) threw exception SyntaxError: Parse error.
PASS (function (a){'use strict'; delete a;})() threw exception SyntaxError: Parse error.
PASS (function(){(function (a){'use strict'; delete a;})()}) threw exception SyntaxError: Parse error.
PASS (function (){'use strict'; var a; delete a;})() threw exception SyntaxError: Parse error.
PASS (function(){(function (){'use strict'; var a; delete a;})()}) threw exception SyntaxError: Parse error.
PASS (function (){var a; function f() {'use strict'; delete a;} })() threw exception SyntaxError: Parse error.
PASS (function(){(function (){var a; function f() {'use strict'; delete a;} })()}) threw exception SyntaxError: Parse error.
PASS (function (){'use strict'; with(1){};}) threw exception SyntaxError: Parse error.
PASS (function(){(function (){'use strict'; with(1){};})}) threw exception SyntaxError: Parse error.
PASS (function (){'use strict'; arguments.callee; })() threw exception TypeError: Unable to access callee of strict mode function.
PASS (function (){'use strict'; arguments.caller; })() threw exception TypeError: Unable to access caller of strict mode function.
PASS (function f(){'use strict'; f.arguments; })() threw exception TypeError: Can't access arguments object of a strict mode function.
......@@ -54,22 +67,37 @@ PASS (function f(arg){'use strict'; f.caller; })() threw exception TypeError: Ca
PASS (function f(arg){'use strict'; f.arguments=5; })() threw exception TypeError: Cannot access arguments property of a strict mode function.
PASS (function f(arg){'use strict'; f.caller=5; })() threw exception TypeError: Cannot access caller property of a strict mode function.
PASS 'use strict'; (function (){with(1){};}) threw exception SyntaxError: Parse error.
PASS (function(){'use strict'; (function (){with(1){};})}) threw exception SyntaxError: Parse error.
PASS 'use strict'; (function (){var a; delete a;}) threw exception SyntaxError: Parse error.
PASS (function(){'use strict'; (function (){var a; delete a;})}) threw exception SyntaxError: Parse error.
PASS 'use strict'; var a; (function (){ delete a;}) threw exception SyntaxError: Parse error.
PASS (function(){'use strict'; var a; (function (){ delete a;})}) threw exception SyntaxError: Parse error.
PASS var a; (function (){ 'use strict'; delete a;}) threw exception SyntaxError: Parse error.
PASS (function(){var a; (function (){ 'use strict'; delete a;})}) threw exception SyntaxError: Parse error.
PASS 'misc directive'; 'use strict'; with({}){} threw exception SyntaxError: Parse error.
PASS (function(){'misc directive'; 'use strict'; with({}){}}) threw exception SyntaxError: Parse error.
PASS 'use strict'; return threw exception SyntaxError: Parse error.
PASS 'use strict'; break threw exception SyntaxError: Parse error.
PASS (function(){'use strict'; break}) threw exception SyntaxError: Parse error.
PASS 'use strict'; continue threw exception SyntaxError: Parse error.
PASS (function(){'use strict'; continue}) threw exception SyntaxError: Parse error.
PASS 'use strict'; for(;;)return threw exception SyntaxError: Parse error.
PASS 'use strict'; for(;;)break missingLabel threw exception SyntaxError: Parse error.
PASS (function(){'use strict'; for(;;)break missingLabel}) threw exception SyntaxError: Parse error.
PASS 'use strict'; for(;;)continue missingLabel threw exception SyntaxError: Parse error.
PASS (function(){'use strict'; for(;;)continue missingLabel}) threw exception SyntaxError: Parse error.
PASS 'use strict'; 007; threw exception SyntaxError: Parse error.
PASS (function(){'use strict'; 007;}) threw exception SyntaxError: Parse error.
PASS 'use strict'; '\007'; threw exception SyntaxError: Parse error.
PASS (function(){'use strict'; '\007';}) threw exception SyntaxError: Parse error.
PASS '\007'; 'use strict'; threw exception SyntaxError: Parse error.
PASS (function(){'\007'; 'use strict';}) threw exception SyntaxError: Parse error.
PASS 'use strict'; delete aDeletableProperty; threw exception SyntaxError: Parse error.
PASS (function(){'use strict'; delete aDeletableProperty;}) threw exception SyntaxError: Parse error.
PASS 'use strict'; (function (){ delete someDeclaredGlobal;}) threw exception SyntaxError: Parse error.
PASS (function(){'use strict'; (function (){ delete someDeclaredGlobal;})}) threw exception SyntaxError: Parse error.
PASS (function (){ 'use strict'; delete someDeclaredGlobal;}) threw exception SyntaxError: Parse error.
PASS (function(){(function (){ 'use strict'; delete someDeclaredGlobal;})}) threw exception SyntaxError: Parse error.
PASS 'use strict'; if (0) { someGlobal = 'Shouldn\'t be able to assign this.'; }; true; is true
PASS 'use strict'; someGlobal = 'Shouldn\'t be able to assign this.'; threw exception ReferenceError: Strict mode forbids implicit creation of global property 'someGlobal'.
PASS 'use strict'; eval('var introducedVariable = "FAIL: variable introduced into containing scope";'); introducedVariable threw exception ReferenceError: Can't find variable: introducedVariable.
......@@ -77,25 +105,44 @@ PASS 'use strict'; objectWithReadonlyProperty.prop = 'fail' threw exception Type
PASS 'use strict'; delete objectWithReadonlyProperty.prop threw exception TypeError: Unable to delete property..
PASS 'use strict'; delete objectWithReadonlyProperty[readonlyPropName] threw exception TypeError: Unable to delete property..
PASS 'use strict'; ++eval threw exception SyntaxError: Parse error.
PASS (function(){'use strict'; ++eval}) threw exception SyntaxError: Parse error.
PASS 'use strict'; eval++ threw exception SyntaxError: Parse error.
PASS (function(){'use strict'; eval++}) threw exception SyntaxError: Parse error.
PASS 'use strict'; --eval threw exception SyntaxError: Parse error.
PASS (function(){'use strict'; --eval}) threw exception SyntaxError: Parse error.
PASS 'use strict'; eval-- threw exception SyntaxError: Parse error.
PASS (function(){'use strict'; eval--}) threw exception SyntaxError: Parse error.
PASS 'use strict'; function f() { ++arguments } threw exception SyntaxError: Parse error.
PASS (function(){'use strict'; function f() { ++arguments }}) threw exception SyntaxError: Parse error.
PASS 'use strict'; function f() { arguments++ } threw exception SyntaxError: Parse error.
PASS (function(){'use strict'; function f() { arguments++ }}) threw exception SyntaxError: Parse error.
PASS 'use strict'; function f() { --arguments } threw exception SyntaxError: Parse error.
PASS (function(){'use strict'; function f() { --arguments }}) threw exception SyntaxError: Parse error.
PASS 'use strict'; function f() { arguments-- } threw exception SyntaxError: Parse error.
PASS global.eval('"use strict"; if (0) ++arguments; true;') is true
PASS (function(){'use strict'; function f() { arguments-- }}) threw exception SyntaxError: Parse error.
PASS global.eval('"use strict"; if (0) ++arguments; true;') threw exception SyntaxError: Parse error.
PASS 'use strict'; ++(1, eval) threw exception ReferenceError: Prefix ++ operator applied to value that is not a reference..
PASS (function(){'use strict'; ++(1, eval)}) threw exception SyntaxError: Parse error.
PASS 'use strict'; (1, eval)++ threw exception ReferenceError: Postfix ++ operator applied to value that is not a reference..
PASS (function(){'use strict'; (1, eval)++}) threw exception SyntaxError: Parse error.
PASS 'use strict'; --(1, eval) threw exception ReferenceError: Prefix -- operator applied to value that is not a reference..
PASS (function(){'use strict'; --(1, eval)}) threw exception SyntaxError: Parse error.
PASS 'use strict'; (1, eval)-- threw exception ReferenceError: Postfix -- operator applied to value that is not a reference..
PASS (function(){'use strict'; (1, eval)--}) threw exception SyntaxError: Parse error.
PASS 'use strict'; function f() { ++(1, arguments) } threw exception SyntaxError: Parse error.
PASS (function(){'use strict'; function f() { ++(1, arguments) }}) threw exception SyntaxError: Parse error.
PASS 'use strict'; function f() { (1, arguments)++ } threw exception SyntaxError: Parse error.
PASS (function(){'use strict'; function f() { (1, arguments)++ }}) threw exception SyntaxError: Parse error.
PASS 'use strict'; function f() { --(1, arguments) } threw exception SyntaxError: Parse error.
PASS (function(){'use strict'; function f() { --(1, arguments) }}) threw exception SyntaxError: Parse error.
PASS 'use strict'; function f() { (1, arguments)-- } threw exception SyntaxError: Parse error.
PASS (function(){'use strict'; function f() { (1, arguments)-- }}) threw exception SyntaxError: Parse error.
PASS 'use strict'; if (0) delete +a.b threw exception SyntaxError: Parse error.
PASS (function(){'use strict'; if (0) delete +a.b}) threw exception SyntaxError: Parse error.
PASS 'use strict'; if (0) delete ++a.b threw exception SyntaxError: Parse error.
PASS (function(){'use strict'; if (0) delete ++a.b}) threw exception SyntaxError: Parse error.
PASS 'use strict'; if (0) delete void a.b threw exception SyntaxError: Parse error.
PASS (function(){'use strict'; if (0) delete void a.b}) threw exception SyntaxError: Parse error.
PASS (function (a){'use strict'; a = false; return a !== arguments[0]; })(true) is true
PASS (function (a){'use strict'; arguments[0] = false; return a !== arguments[0]; })(true) is true
PASS (function (a){'use strict'; a=false; return arguments; })(true)[0] is true
......@@ -128,9 +175,23 @@ PASS (function f(arg){'use strict'; var descriptor = Object.getOwnPropertyDescri
PASS (function f(arg){'use strict'; var descriptor = Object.getOwnPropertyDescriptor(f, 'arguments'); return descriptor.get === descriptor.set; })() is true
PASS 'use strict'; (function f() { for(var i in this); })(); true; is true
PASS 'use strict'̻ threw exception SyntaxError: Parse error.
PASS (function(){'use strict'̻}) threw exception SyntaxError: Parse error.
PASS 'use strict'5.f threw exception SyntaxError: Parse error.
PASS (function(){'use strict'5.f}) threw exception SyntaxError: Parse error.
PASS 'use strict';̻ threw exception SyntaxError: Parse error.
PASS (function(){'use strict';̻}) threw exception SyntaxError: Parse error.
PASS 'use strict';5.f threw exception SyntaxError: Parse error.
PASS (function(){'use strict';5.f}) threw exception SyntaxError: Parse error.
PASS 'use strict';1-(eval=1); threw exception SyntaxError: Parse error.
PASS (function(){'use strict';1-(eval=1);}) threw exception SyntaxError: Parse error.
PASS 'use strict';arguments=1; threw exception SyntaxError: Parse error.
PASS (function(){'use strict';arguments=1;}) threw exception SyntaxError: Parse error.
PASS 'use strict';1-(arguments=1); threw exception SyntaxError: Parse error.
PASS (function(){'use strict';1-(arguments=1);}) threw exception SyntaxError: Parse error.
PASS 'use strict';var a=(eval=1); threw exception SyntaxError: Parse error.
PASS (function(){'use strict';var a=(eval=1);}) threw exception SyntaxError: Parse error.
PASS 'use strict';var a=(arguments=1); threw exception SyntaxError: Parse error.
PASS (function(){'use strict';var a=(arguments=1);}) threw exception SyntaxError: Parse error.
PASS successfullyParsed is true
TEST COMPLETE
......
......@@ -16,6 +16,11 @@ function testThisBracketAccess(prop) {
function testGlobalAccess() {
return testThis();
}
function shouldBeSyntaxError(str) {
shouldThrow(str);
shouldThrow("(function(){" + str + "})");
}
shouldBe("testThis.call(null)", "null");
shouldBe("testThis.call(1)", "1");
shouldBe("testThis.call(true)", "true");
......@@ -44,19 +49,19 @@ shouldBe("testThis.apply()", "undefined");
shouldBe("testThis.call(undefined)", "undefined");
shouldBe("testThis.apply(undefined)", "undefined");
shouldThrow("(function eval(){'use strict';})");
shouldThrow("(function (eval){'use strict';})");
shouldThrow("(function arguments(){'use strict';})");
shouldThrow("(function (arguments){'use strict';})");
shouldThrow("(function (){'use strict'; var eval;})");
shouldThrow("(function (){'use strict'; var arguments;})");
shouldThrow("(function (){'use strict'; try{}catch(eval){}})");
shouldThrow("(function (){'use strict'; try{}catch(arguments){}})");
shouldThrow("(function (a, a){'use strict';})");
shouldThrow("(function (a){'use strict'; delete a;})()");
shouldThrow("(function (){'use strict'; var a; delete a;})()");
shouldThrow("(function (){var a; function f() {'use strict'; delete a;} })()");
shouldThrow("(function (){'use strict'; with(1){};})");
shouldBeSyntaxError("(function eval(){'use strict';})");
shouldBeSyntaxError("(function (eval){'use strict';})");
shouldBeSyntaxError("(function arguments(){'use strict';})");
shouldBeSyntaxError("(function (arguments){'use strict';})");
shouldBeSyntaxError("(function (){'use strict'; var eval;})");
shouldBeSyntaxError("(function (){'use strict'; var arguments;})");
shouldBeSyntaxError("(function (){'use strict'; try{}catch(eval){}})");
shouldBeSyntaxError("(function (){'use strict'; try{}catch(arguments){}})");
shouldBeSyntaxError("(function (a, a){'use strict';})");
shouldBeSyntaxError("(function (a){'use strict'; delete a;})()");
shouldBeSyntaxError("(function (){'use strict'; var a; delete a;})()");
shouldBeSyntaxError("(function (){var a; function f() {'use strict'; delete a;} })()");
shouldBeSyntaxError("(function (){'use strict'; with(1){};})");
shouldThrow("(function (){'use strict'; arguments.callee; })()");
shouldThrow("(function (){'use strict'; arguments.caller; })()");
shouldThrow("(function f(){'use strict'; f.arguments; })()");
......@@ -69,27 +74,27 @@ shouldThrow("(function f(arg){'use strict'; f.arguments; })()");
shouldThrow("(function f(arg){'use strict'; f.caller; })()");
shouldThrow("(function f(arg){'use strict'; f.arguments=5; })()");
shouldThrow("(function f(arg){'use strict'; f.caller=5; })()");
shouldThrow("'use strict'; (function (){with(1){};})");
shouldThrow("'use strict'; (function (){var a; delete a;})");
shouldThrow("'use strict'; var a; (function (){ delete a;})");
shouldThrow("var a; (function (){ 'use strict'; delete a;})");
shouldThrow("'misc directive'; 'use strict'; with({}){}");
shouldBeSyntaxError("'use strict'; (function (){with(1){};})");
shouldBeSyntaxError("'use strict'; (function (){var a; delete a;})");
shouldBeSyntaxError("'use strict'; var a; (function (){ delete a;})");
shouldBeSyntaxError("var a; (function (){ 'use strict'; delete a;})");
shouldBeSyntaxError("'misc directive'; 'use strict'; with({}){}");
shouldThrow("'use strict'; return");
shouldThrow("'use strict'; break");
shouldThrow("'use strict'; continue");
shouldBeSyntaxError("'use strict'; break");
shouldBeSyntaxError("'use strict'; continue");
shouldThrow("'use strict'; for(;;)return");
shouldThrow("'use strict'; for(;;)break missingLabel");
shouldThrow("'use strict'; for(;;)continue missingLabel");
shouldThrow("'use strict'; 007;");
shouldThrow("'use strict'; '\\007';");
shouldThrow("'\\007'; 'use strict';");
shouldBeSyntaxError("'use strict'; for(;;)break missingLabel");
shouldBeSyntaxError("'use strict'; for(;;)continue missingLabel");
shouldBeSyntaxError("'use strict'; 007;");
shouldBeSyntaxError("'use strict'; '\\007';");
shouldBeSyntaxError("'\\007'; 'use strict';");
var someDeclaredGlobal;
aDeletableProperty = 'test';
shouldThrow("'use strict'; delete aDeletableProperty;");
shouldThrow("'use strict'; (function (){ delete someDeclaredGlobal;})");
shouldThrow("(function (){ 'use strict'; delete someDeclaredGlobal;})");
shouldBeSyntaxError("'use strict'; delete aDeletableProperty;");
shouldBeSyntaxError("'use strict'; (function (){ delete someDeclaredGlobal;})");
shouldBeSyntaxError("(function (){ 'use strict'; delete someDeclaredGlobal;})");
shouldBeTrue("'use strict'; if (0) { someGlobal = 'Shouldn\\'t be able to assign this.'; }; true;");
shouldThrow("'use strict'; someGlobal = 'Shouldn\\'t be able to assign this.'; ");
shouldThrow("'use strict'; eval('var introducedVariable = \"FAIL: variable introduced into containing scope\";'); introducedVariable");
......@@ -99,27 +104,27 @@ shouldThrow("'use strict'; objectWithReadonlyProperty.prop = 'fail'");
shouldThrow("'use strict'; delete objectWithReadonlyProperty.prop");
readonlyPropName = "prop";
shouldThrow("'use strict'; delete objectWithReadonlyProperty[readonlyPropName]");
shouldThrow("'use strict'; ++eval");
shouldThrow("'use strict'; eval++");
shouldThrow("'use strict'; --eval");
shouldThrow("'use strict'; eval--");
shouldThrow("'use strict'; function f() { ++arguments }");
shouldThrow("'use strict'; function f() { arguments++ }");
shouldThrow("'use strict'; function f() { --arguments }");
shouldThrow("'use strict'; function f() { arguments-- }");
shouldBeSyntaxError("'use strict'; ++eval");
shouldBeSyntaxError("'use strict'; eval++");
shouldBeSyntaxError("'use strict'; --eval");
shouldBeSyntaxError("'use strict'; eval--");
shouldBeSyntaxError("'use strict'; function f() { ++arguments }");
shouldBeSyntaxError("'use strict'; function f() { arguments++ }");
shouldBeSyntaxError("'use strict'; function f() { --arguments }");
shouldBeSyntaxError("'use strict'; function f() { arguments-- }");
var global = this;
shouldBeTrue("global.eval('\"use strict\"; if (0) ++arguments; true;')");
shouldThrow("'use strict'; ++(1, eval)");
shouldThrow("'use strict'; (1, eval)++");
shouldThrow("'use strict'; --(1, eval)");
shouldThrow("'use strict'; (1, eval)--");
shouldThrow("'use strict'; function f() { ++(1, arguments) }");
shouldThrow("'use strict'; function f() { (1, arguments)++ }");
shouldThrow("'use strict'; function f() { --(1, arguments) }");
shouldThrow("'use strict'; function f() { (1, arguments)-- }");
shouldThrow("'use strict'; if (0) delete +a.b");
shouldThrow("'use strict'; if (0) delete ++a.b");
shouldThrow("'use strict'; if (0) delete void a.b");
shouldThrow("global.eval('\"use strict\"; if (0) ++arguments; true;')");
shouldBeSyntaxError("'use strict'; ++(1, eval)");
shouldBeSyntaxError("'use strict'; (1, eval)++");
shouldBeSyntaxError("'use strict'; --(1, eval)");
shouldBeSyntaxError("'use strict'; (1, eval)--");
shouldBeSyntaxError("'use strict'; function f() { ++(1, arguments) }");
shouldBeSyntaxError("'use strict'; function f() { (1, arguments)++ }");
shouldBeSyntaxError("'use strict'; function f() { --(1, arguments) }");
shouldBeSyntaxError("'use strict'; function f() { (1, arguments)-- }");
shouldBeSyntaxError("'use strict'; if (0) delete +a.b");
shouldBeSyntaxError("'use strict'; if (0) delete ++a.b");
shouldBeSyntaxError("'use strict'; if (0) delete void a.b");
shouldBeTrue("(function (a){'use strict'; a = false; return a !== arguments[0]; })(true)");
shouldBeTrue("(function (a){'use strict'; arguments[0] = false; return a !== arguments[0]; })(true)");
......@@ -157,9 +162,13 @@ shouldBeTrue("(function f(arg){'use strict'; var descriptor = Object.getOwnPrope
shouldBeTrue("(function f(arg){'use strict'; var descriptor = Object.getOwnPropertyDescriptor(f, 'arguments'); return descriptor.get === descriptor.set; })()");
shouldBeTrue("'use strict'; (function f() { for(var i in this); })(); true;")
shouldThrow("'use strict'\u033b");
shouldThrow("'use strict'5.f");
shouldThrow("'use strict';\u033b");
shouldThrow("'use strict';5.f");
shouldBeSyntaxError("'use strict'\u033b");
shouldBeSyntaxError("'use strict'5.f");
shouldBeSyntaxError("'use strict';\u033b");
shouldBeSyntaxError("'use strict';5.f");
shouldBeSyntaxError("'use strict';1-(eval=1);");
shouldBeSyntaxError("'use strict';arguments=1;");
shouldBeSyntaxError("'use strict';1-(arguments=1);");
shouldBeSyntaxError("'use strict';var a=(eval=1);");
shouldBeSyntaxError("'use strict';var a=(arguments=1);");
var successfullyParsed = true;
2011-01-16 Oliver Hunt <oliver@apple.com>
Reviewed by Geoffrey Garen.
Strict mode restrictions on arguments and eval usage aren't complete
https://bugs.webkit.org/show_bug.cgi?id=52528
Fix a few bugs in strict mode where we incorrect allow mutation of
arguments and eval in the parser.
Alas the "optimisation" used by the syntax checker for validating
binary and unary expressions was too aggressive: we do actually need
a stack for operations and operands although it needn't be as complete
as that used for the full AST builder.
Also disallow assignment to arguments in all cases as allowing arguments
to be assignable is always an error in strict mode, regardless of context.
* parser/ASTBuilder.h:
(JSC::ASTBuilder::BinaryExprContext::BinaryExprContext):
(JSC::ASTBuilder::UnaryExprContext::UnaryExprContext):
* parser/JSParser.cpp:
(JSC::JSParser::parseAssignmentExpression):
(JSC::JSParser::parseBinaryExpression):
(JSC::JSParser::parseUnaryExpression):
* parser/SyntaxChecker.h:
(JSC::SyntaxChecker::BinaryExprContext::BinaryExprContext):
(JSC::SyntaxChecker::BinaryExprContext::~BinaryExprContext):
(JSC::SyntaxChecker::UnaryExprContext::UnaryExprContext):
(JSC::SyntaxChecker::UnaryExprContext::~UnaryExprContext):
(JSC::SyntaxChecker::appendBinaryExpressionInfo):
(JSC::SyntaxChecker::operatorStackPop):
2011-01-15 Geoffrey Garen <ggaren@apple.com>
 
Reviewed by Oliver Hunt.
......
......@@ -80,6 +80,13 @@ public:
{
m_scopes.append(Scope(globalData));
}
struct BinaryExprContext {
BinaryExprContext(ASTBuilder&) {}
};
struct UnaryExprContext {
UnaryExprContext(ASTBuilder&) {}
};
typedef SyntaxChecker FunctionBodyBuilder;
......
......@@ -1490,6 +1490,7 @@ template <typename TreeBuilder> TreeExpression JSParser::parseAssignmentExpressi
next();
if (strictMode() && m_lastIdentifier && context.isResolve(lhs)) {
failIfTrueIfStrict(m_globalData->propertyNames->eval == *m_lastIdentifier);
failIfTrueIfStrict(m_globalData->propertyNames->arguments == *m_lastIdentifier);
declareWrite(m_lastIdentifier);
m_lastIdentifier = 0;
}
......@@ -1545,6 +1546,7 @@ template <class TreeBuilder> TreeExpression JSParser::parseBinaryExpression(Tree
int operandStackDepth = 0;
int operatorStackDepth = 0;
typename TreeBuilder::BinaryExprContext binaryExprContext(context);
while (true) {
int exprStart = tokenStart();
int initialAssignments = m_assignmentCount;
......@@ -1942,6 +1944,7 @@ endMemberExpression:
template <class TreeBuilder> TreeExpression JSParser::parseUnaryExpression(TreeBuilder& context)
{
typename TreeBuilder::UnaryExprContext unaryExprContext(context);
AllowInOverride allowInOverride(this);
int tokenStackDepth = 0;
bool modifiesExpr = false;
......@@ -1977,9 +1980,7 @@ template <class TreeBuilder> TreeExpression JSParser::parseUnaryExpression(TreeB
bool isEvalOrArguments = false;
if (strictMode() && !m_syntaxAlreadyValidated) {
if (context.isResolve(expr)) {
isEvalOrArguments = m_globalData->propertyNames->eval == *m_lastIdentifier;
if (!isEvalOrArguments && currentScope()->isFunction())
isEvalOrArguments = m_globalData->propertyNames->arguments == *m_lastIdentifier;
isEvalOrArguments = *m_lastIdentifier == m_globalData->propertyNames->eval || *m_lastIdentifier == m_globalData->propertyNames->arguments;
}
}
failIfTrueIfStrict(isEvalOrArguments && modifiesExpr);
......
......@@ -31,8 +31,38 @@
namespace JSC {
class SyntaxChecker {
public:
struct BinaryExprContext {
BinaryExprContext(SyntaxChecker& context)
: m_context(&context)
{
m_context->m_topBinaryExprs.append(m_context->m_topBinaryExpr);
m_context->m_topBinaryExpr = 0;
}
~BinaryExprContext()
{
m_context->m_topBinaryExpr = m_context->m_topBinaryExprs.last();
m_context->m_topBinaryExprs.removeLast();
}
private:
SyntaxChecker* m_context;
};
struct UnaryExprContext {
UnaryExprContext(SyntaxChecker& context)
: m_context(&context)
{
m_context->m_topUnaryTokens.append(m_context->m_topUnaryToken);
m_context->m_topUnaryToken = 0;
}
~UnaryExprContext()
{
m_context->m_topUnaryToken = m_context->m_topUnaryTokens.last();
m_context->m_topUnaryTokens.removeLast();
}
private:
SyntaxChecker* m_context;
};
SyntaxChecker(JSGlobalData* , Lexer*)
: m_topBinaryExpr(0)
{
}
......@@ -212,6 +242,8 @@ public:
private:
int m_topBinaryExpr;
int m_topUnaryToken;
Vector<int, 8> m_topBinaryExprs;
Vector<int, 8> m_topUnaryTokens;
};
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment