diff options
author | Lars Knoll <lars.knoll@qt.io> | 2018-04-12 09:18:04 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2018-04-25 17:50:33 +0000 |
commit | 9f731b6841bbc9b7425a95303369d05be895f949 (patch) | |
tree | b3a34152a06f5066d0b60b4d0e3f30333e6c2d0e /src/qml | |
parent | e2ed846dd4710268a208962f3217b79994e8cb31 (diff) |
Fix crashes when parsing some invalid JS
function foo() { let x; function x() {} }
would crash. Throw an error instead now.
Change-Id: I5e5588deb21c1777be15a6656baefc422d59ff0c
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml')
-rw-r--r-- | src/qml/compiler/qv4compilerscanfunctions.cpp | 25 | ||||
-rw-r--r-- | src/qml/compiler/qv4compilerscanfunctions_p.h | 4 |
2 files changed, 14 insertions, 15 deletions
diff --git a/src/qml/compiler/qv4compilerscanfunctions.cpp b/src/qml/compiler/qv4compilerscanfunctions.cpp index 5b7103323e..3f7211b95e 100644 --- a/src/qml/compiler/qv4compilerscanfunctions.cpp +++ b/src/qml/compiler/qv4compilerscanfunctions.cpp @@ -225,7 +225,8 @@ bool ScanFunctions::visit(ExpressionStatement *ast) if (!_allowFuncDecls) _cg->throwSyntaxError(expr->functionToken, QStringLiteral("conditional function or closure declaration")); - enterFunction(expr, /*enterName*/ true); + if (!enterFunction(expr, /*enterName*/ true)) + return false; Node::accept(expr->formals, this); Node::accept(expr->body, this); leaveEnvironment(); @@ -241,8 +242,7 @@ bool ScanFunctions::visit(ExpressionStatement *ast) bool ScanFunctions::visit(FunctionExpression *ast) { - enterFunction(ast, /*enterName*/ false); - return true; + return enterFunction(ast, /*enterName*/ false); } bool ScanFunctions::visit(TemplateLiteral *ast) @@ -256,11 +256,11 @@ bool ScanFunctions::visit(TemplateLiteral *ast) } -void ScanFunctions::enterFunction(FunctionExpression *ast, bool enterName) +bool ScanFunctions::enterFunction(FunctionExpression *ast, bool enterName) { if (_context->isStrict && (ast->name == QLatin1String("eval") || ast->name == QLatin1String("arguments"))) _cg->throwSyntaxError(ast->identifierToken, QStringLiteral("Function name may not be eval or arguments in strict mode")); - enterFunction(ast, ast->name.toString(), ast->formals, ast->body, enterName ? ast : nullptr); + return enterFunction(ast, ast->name.toString(), ast->formals, ast->body, enterName ? ast : nullptr); } void ScanFunctions::endVisit(FunctionExpression *) @@ -289,8 +289,7 @@ bool ScanFunctions::visit(ObjectLiteral *ast) bool ScanFunctions::visit(PropertyGetterSetter *ast) { TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, true); - enterFunction(ast, QString(), ast->formals, ast->functionBody, /*FunctionExpression*/nullptr); - return true; + return enterFunction(ast, QString(), ast->formals, ast->functionBody, /*FunctionExpression*/nullptr); } void ScanFunctions::endVisit(PropertyGetterSetter *) @@ -300,8 +299,7 @@ void ScanFunctions::endVisit(PropertyGetterSetter *) bool ScanFunctions::visit(FunctionDeclaration *ast) { - enterFunction(ast, /*enterName*/ true); - return true; + return enterFunction(ast, /*enterName*/ true); } void ScanFunctions::endVisit(FunctionDeclaration *) @@ -390,7 +388,7 @@ bool ScanFunctions::visit(Block *ast) { return false; } -void ScanFunctions::enterFunction(Node *ast, const QString &name, FormalParameterList *formals, StatementList *body, FunctionExpression *expr) +bool ScanFunctions::enterFunction(Node *ast, const QString &name, FormalParameterList *formals, StatementList *body, FunctionExpression *expr) { Context *outerContext = _context; enterEnvironment(ast, FunctionCode); @@ -401,7 +399,7 @@ void ScanFunctions::enterFunction(Node *ast, const QString &name, FormalParamete if (expr) { if (!outerContext->addLocalVar(name, Context::FunctionDefinition, AST::VariableDeclaration::FunctionScope, expr)) { _cg->throwSyntaxError(ast->firstSourceLocation(), QStringLiteral("Identifier %1 has already been declared").arg(name)); - return; + return false; } } if (name == QLatin1String("arguments")) @@ -430,18 +428,19 @@ void ScanFunctions::enterFunction(Node *ast, const QString &name, FormalParamete bool duplicate = (boundNames.indexOf(arg, i + 1) != -1); if (duplicate) { _cg->throwSyntaxError(formals->firstSourceLocation(), QStringLiteral("Duplicate parameter name '%1' is not allowed.").arg(arg)); - return; + return false; } } if (_context->isStrict) { if (arg == QLatin1String("eval") || arg == QLatin1String("arguments")) { _cg->throwSyntaxError(formals->firstSourceLocation(), QStringLiteral("'%1' cannot be used as parameter name in strict mode").arg(arg)); - return; + return false; } } if (!_context->arguments.contains(arg)) _context->addLocalVar(arg, Context::VariableDefinition, QQmlJS::AST::VariableDeclaration::FunctionScope); } + return true; } void ScanFunctions::calcEscapingVariables() diff --git a/src/qml/compiler/qv4compilerscanfunctions_p.h b/src/qml/compiler/qv4compilerscanfunctions_p.h index 940bd9f73a..cf79da2203 100644 --- a/src/qml/compiler/qv4compilerscanfunctions_p.h +++ b/src/qml/compiler/qv4compilerscanfunctions_p.h @@ -111,7 +111,7 @@ protected: bool visit(AST::FunctionExpression *ast) override; bool visit(AST::TemplateLiteral *ast) override; - void enterFunction(AST::FunctionExpression *ast, bool enterName); + bool enterFunction(AST::FunctionExpression *ast, bool enterName); void endVisit(AST::FunctionExpression *) override; @@ -136,7 +136,7 @@ protected: bool visit(AST::Block *ast) override; protected: - void enterFunction(AST::Node *ast, const QString &name, AST::FormalParameterList *formals, AST::StatementList *body, AST::FunctionExpression *expr); + bool enterFunction(AST::Node *ast, const QString &name, AST::FormalParameterList *formals, AST::StatementList *body, AST::FunctionExpression *expr); void calcEscapingVariables(); // fields: |