| Index: src/asmjs/asm-typer.cc
|
| diff --git a/src/asmjs/asm-typer.cc b/src/asmjs/asm-typer.cc
|
| index 165ef9e148faf65e0b4e29701d7ba9b5edf97d07..1a3f932c93dc4eb7289c8a1ab6d69e3b588baf09 100644
|
| --- a/src/asmjs/asm-typer.cc
|
| +++ b/src/asmjs/asm-typer.cc
|
| @@ -4,6 +4,7 @@
|
|
|
| #include "src/asmjs/asm-typer.h"
|
|
|
| +#include <algorithm>
|
| #include <limits>
|
| #include <string>
|
|
|
| @@ -466,7 +467,89 @@ Assignment* ExtractInitializerExpression(Statement* statement) {
|
| } // namespace
|
|
|
| // 6.1 ValidateModule
|
| +namespace {
|
| +// SourceLayoutTracker keeps track of the start and end positions of each
|
| +// section in the asm.js source. The sections should not overlap, otherwise the
|
| +// asm.js source is invalid.
|
| +class SourceLayoutTracker {
|
| + public:
|
| + SourceLayoutTracker() = default;
|
| +
|
| + bool IsValid() const {
|
| + const Section* kAllSections[] = {&use_asm_, &globals_, &functions_,
|
| + &tables_, &exports_};
|
| + for (size_t ii = 0; ii < arraysize(kAllSections); ++ii) {
|
| + const auto& curr_section = *kAllSections[ii];
|
| + for (size_t jj = ii + 1; jj < arraysize(kAllSections); ++jj) {
|
| + if (curr_section.OverlapsWith(*kAllSections[jj])) {
|
| + return false;
|
| + }
|
| + }
|
| + }
|
| + return true;
|
| + }
|
| +
|
| + void AddUseAsm(const AstNode& node) { use_asm_.AddNewElement(node); }
|
| +
|
| + void AddGlobal(const AstNode& node) { globals_.AddNewElement(node); }
|
| +
|
| + void AddFunction(const AstNode& node) { functions_.AddNewElement(node); }
|
| +
|
| + void AddTable(const AstNode& node) { tables_.AddNewElement(node); }
|
| +
|
| + void AddExport(const AstNode& node) { exports_.AddNewElement(node); }
|
| +
|
| + private:
|
| + class Section {
|
| + public:
|
| + Section() = default;
|
| + Section(const Section&) = default;
|
| + Section& operator=(const Section&) = default;
|
| +
|
| + void AddNewElement(const AstNode& node) {
|
| + const int node_pos = node.position();
|
| + if (start_ == kNoSourcePosition) {
|
| + start_ = node_pos;
|
| + } else {
|
| + start_ = std::max(start_, node_pos);
|
| + }
|
| + if (end_ == kNoSourcePosition) {
|
| + end_ = node_pos;
|
| + } else {
|
| + end_ = std::max(end_, node_pos);
|
| + }
|
| + }
|
| +
|
| + bool OverlapsWith(const Section& other) const {
|
| + if (start_ == kNoSourcePosition) {
|
| + DCHECK_EQ(end_, kNoSourcePosition);
|
| + return false;
|
| + }
|
| + if (other.start_ == kNoSourcePosition) {
|
| + DCHECK_EQ(other.end_, kNoSourcePosition);
|
| + return false;
|
| + }
|
| + return other.start_ < end_ || other.end_ < start_;
|
| + }
|
| +
|
| + private:
|
| + int start_ = kNoSourcePosition;
|
| + int end_ = kNoSourcePosition;
|
| + };
|
| +
|
| + Section use_asm_;
|
| + Section globals_;
|
| + Section functions_;
|
| + Section tables_;
|
| + Section exports_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(SourceLayoutTracker);
|
| +};
|
| +} // namespace
|
| +
|
| AsmType* AsmTyper::ValidateModule(FunctionLiteral* fun) {
|
| + SourceLayoutTracker source_layout;
|
| +
|
| Scope* scope = fun->scope();
|
| if (!scope->is_function_scope()) FAIL(fun, "Not at function scope.");
|
| if (!ValidAsmIdentifier(fun->name()))
|
| @@ -507,6 +590,7 @@ AsmType* AsmTyper::ValidateModule(FunctionLiteral* fun) {
|
| if (use_asm_directive == nullptr || !IsUseAsmDirective(use_asm_directive)) {
|
| FAIL(fun, "Missing \"use asm\".");
|
| }
|
| + source_layout.AddUseAsm(*use_asm_directive);
|
| ReturnStatement* module_return = nullptr;
|
|
|
| // *VIOLATION* The spec states that globals should be followed by function
|
| @@ -520,6 +604,7 @@ AsmType* AsmTyper::ValidateModule(FunctionLiteral* fun) {
|
| function_pointer_tables.push_back(assign);
|
| } else {
|
| RECURSE(ValidateGlobalDeclaration(assign));
|
| + source_layout.AddGlobal(*assign);
|
| }
|
| continue;
|
| }
|
| @@ -529,6 +614,7 @@ AsmType* AsmTyper::ValidateModule(FunctionLiteral* fun) {
|
| FAIL(fun, "Multiple export statements.");
|
| }
|
| module_return = current_as_return;
|
| + source_layout.AddExport(*module_return);
|
| continue;
|
| }
|
|
|
| @@ -542,12 +628,14 @@ AsmType* AsmTyper::ValidateModule(FunctionLiteral* fun) {
|
|
|
| if (FunctionDeclaration* fun_decl = decl->AsFunctionDeclaration()) {
|
| RECURSE(ValidateFunction(fun_decl));
|
| + source_layout.AddFunction(*fun_decl);
|
| continue;
|
| }
|
| }
|
|
|
| for (auto* function_table : function_pointer_tables) {
|
| RECURSE(ValidateFunctionTable(function_table));
|
| + source_layout.AddTable(*function_table);
|
| }
|
|
|
| for (int ii = 0; ii < decls->length(); ++ii) {
|
| @@ -586,6 +674,10 @@ AsmType* AsmTyper::ValidateModule(FunctionLiteral* fun) {
|
|
|
| RECURSE(ValidateExport(module_return));
|
|
|
| + if (!source_layout.IsValid()) {
|
| + FAIL(fun, "Invalid asm.js source code layout.");
|
| + }
|
| +
|
| return AsmType::Int(); // Any type that is not AsmType::None();
|
| }
|
|
|
|
|