Commit a25e9c6f authored by jpp's avatar jpp Committed by Commit bot

V8. ASM-2-WASM. Fixes issue 628446.

The issue was caused by a mishandling of "special" identifiers, i.e.,
the module's name, and the module's parameter.

BUG= https://bugs.chromium.org/p/chromium/issues/detail?id=628446
BUG= https://bugs.chromium.org/p/v8/issues/detail?id=4203
TEST= cctest/asmjs/test-asm-typer.cc
TEST= cctest/wasm/*
LOG=N

Review-Url: https://codereview.chromium.org/2147403002
Cr-Commit-Position: refs/heads/master@{#37800}
parent cecded1c
......@@ -92,8 +92,19 @@ Statement* AsmTyper::FlattenedStatements::Next() {
// ----------------------------------------------------------------------------
// Implementation of AsmTyper::VariableInfo
AsmTyper::VariableInfo* AsmTyper::VariableInfo::ForSpecialSymbol(
Zone* zone, StandardMember standard_member) {
DCHECK(standard_member == kStdlib || standard_member == kFFI ||
standard_member == kHeap || standard_member == kModule);
auto* new_var_info = new (zone) VariableInfo(AsmType::None());
new_var_info->standard_member_ = standard_member;
new_var_info->mutability_ = kImmutableGlobal;
return new_var_info;
}
AsmTyper::VariableInfo* AsmTyper::VariableInfo::Clone(Zone* zone) const {
CHECK(standard_member_ != kNone);
CHECK(!type_->IsA(AsmType::None()));
auto* new_var_info = new (zone) VariableInfo(type_);
new_var_info->standard_member_ = standard_member_;
new_var_info->mutability_ = mutability_;
......@@ -118,6 +129,7 @@ AsmTyper::AsmTyper(Isolate* isolate, Zone* zone, Script* script,
forward_definitions_(zone),
stdlib_types_(zone),
stdlib_math_types_(zone),
module_info_(VariableInfo::ForSpecialSymbol(zone_, kModule)),
global_scope_(ZoneHashMap::PointersMatch,
ZoneHashMap::kDefaultHashMapCapacity,
ZoneAllocationPolicy(zone)),
......@@ -126,9 +138,9 @@ AsmTyper::AsmTyper(Isolate* isolate, Zone* zone, Script* script,
ZoneAllocationPolicy(zone)),
stack_limit_(isolate->stack_guard()->real_climit()),
node_types_(zone_),
fround_type_(AsmType::FroundType(zone_)) {
fround_type_(AsmType::FroundType(zone_)),
ffi_type_(AsmType::FFIType(zone_)) {
InitializeStdlib();
module_info_.set_standard_member(kModule);
}
namespace {
......@@ -318,7 +330,7 @@ AsmTyper::VariableInfo* AsmTyper::Lookup(Variable* variable) {
if (entry == nullptr && !module_name_.is_null() &&
module_name_->Equals(*variable->name())) {
return &module_info_;
return module_info_;
}
return entry ? reinterpret_cast<VariableInfo*>(entry->value) : nullptr;
......@@ -469,11 +481,8 @@ AsmType* AsmTyper::ValidateModule(FunctionLiteral* fun) {
struct {
StandardMember standard_member;
AsmType* type;
} kModuleParamInfo[3] = {
{kStdlib, AsmType::None()},
{kFFI, AsmType::FFIType(zone_)},
{kHeap, AsmType::None()},
{kStdlib}, {kFFI}, {kHeap},
};
for (int ii = 0; ii < scope->num_parameters(); ++ii) {
......@@ -484,10 +493,8 @@ AsmType* AsmTyper::ValidateModule(FunctionLiteral* fun) {
FAIL(fun, "Invalid asm.js identifier in module parameter.");
}
auto* param_info = new (zone_) VariableInfo();
param_info->set_mutability(VariableInfo::kImmutableGlobal);
param_info->set_standard_member(kModuleParamInfo[ii].standard_member);
param_info->set_type(kModuleParamInfo[ii].type);
auto* param_info = VariableInfo::ForSpecialSymbol(
zone_, kModuleParamInfo[ii].standard_member);
if (!AddGlobal(param, param_info)) {
FAIL(fun, "Redeclared identifier in module parameter.");
......@@ -649,8 +656,7 @@ AsmType* AsmTyper::ValidateGlobalDeclaration(Assignment* assign) {
CHECK(target_info->mutability() == VariableInfo::kImmutableGlobal);
if (target_info->IsFFI()) {
// create a new target info that represents a foreign variable.
DCHECK(target_info->type()->AsFFIType() != nullptr);
target_info = new (zone_) VariableInfo(target_info->type());
target_info = new (zone_) VariableInfo(ffi_type_);
target_info->set_mutability(VariableInfo::kImmutableGlobal);
} else if (target_info->type()->IsA(AsmType::Heap())) {
FAIL(assign, "Heap view types can not be aliased.");
......@@ -697,7 +703,6 @@ AsmType* AsmTyper::ValidateGlobalDeclaration(Assignment* assign) {
}
// Create a new target info that represents the foreign import.
DCHECK(target_info->type()->AsFFIType() != nullptr);
target_info = new (zone_) VariableInfo(import_type);
target_info->set_mutability(VariableInfo::kMutableGlobal);
} else if (value->IsCallNew()) {
......@@ -1553,11 +1558,11 @@ AsmType* AsmTyper::ValidateIdentifier(VariableProxy* proxy) {
if (proxy_info == nullptr) {
FAIL(proxy, "Undeclared identifier.");
}
if (proxy_info->type()->AsCallableType() != nullptr) {
auto* type = proxy_info->type();
if (type->IsA(AsmType::None()) || type->AsCallableType() != nullptr) {
FAIL(proxy, "Identifier may not be accessed by ordinary expressions.");
}
DCHECK(!proxy_info->type()->IsA(AsmType::None()));
return proxy_info->type();
return type;
}
// 6.8.4 CallExpression
......
......@@ -85,7 +85,6 @@ class AsmTyper final {
kImmutableGlobal,
};
VariableInfo() = default;
explicit VariableInfo(AsmType* t) : type_(t) {}
VariableInfo* Clone(Zone* zone) const;
......@@ -120,8 +119,11 @@ class AsmTyper final {
VariableProxy* first_forward_use() const { return first_forward_use_; }
static VariableInfo* ForSpecialSymbol(Zone* zone,
StandardMember standard_member);
private:
AsmType* type_ = AsmType::None();
AsmType* type_;
StandardMember standard_member_ = kNone;
Mutability mutability_ = kInvalidMutability;
// missing_definition_ is set to true for forward definition - i.e., use
......@@ -303,7 +305,7 @@ class AsmTyper final {
// The ASM module name. This member is used to prevent globals from redefining
// the module name.
VariableInfo module_info_;
VariableInfo* module_info_;
Handle<String> module_name_;
// 3 Environments
......@@ -315,6 +317,7 @@ class AsmTyper final {
ZoneMap<AstNode*, AsmType*> node_types_;
static const int kErrorMessageLimit = 100;
AsmType* fround_type_;
AsmType* ffi_type_;
char error_message_[kErrorMessageLimit];
DISALLOW_IMPLICIT_CONSTRUCTORS(AsmTyper);
......
......@@ -177,18 +177,16 @@ class AsmTyperHarnessBuilder {
AsmTyperHarnessBuilder* WithStdlib(VariableName var_name) {
auto* var = DeclareVariable(var_name);
auto* var_info = new (zone_) AsmTyper::VariableInfo();
var_info->set_mutability(AsmTyper::VariableInfo::kImmutableGlobal);
var_info->set_standard_member(AsmTyper::kStdlib);
auto* var_info =
AsmTyper::VariableInfo::ForSpecialSymbol(zone_, AsmTyper::kStdlib);
CHECK(typer_->AddGlobal(var, var_info));
return this;
}
AsmTyperHarnessBuilder* WithHeap(VariableName var_name) {
auto* var = DeclareVariable(var_name);
auto* var_info = new (zone_) AsmTyper::VariableInfo();
var_info->set_mutability(AsmTyper::VariableInfo::kImmutableGlobal);
var_info->set_standard_member(AsmTyper::kHeap);
auto* var_info =
AsmTyper::VariableInfo::ForSpecialSymbol(zone_, AsmTyper::kHeap);
CHECK(typer_->AddGlobal(var, var_info));
return this;
}
......@@ -196,9 +194,7 @@ class AsmTyperHarnessBuilder {
AsmTyperHarnessBuilder* WithFFI(VariableName var_name) {
auto* var = DeclareVariable(var_name);
auto* var_info =
new (zone_) AsmTyper::VariableInfo(AsmType::FFIType(zone_));
var_info->set_mutability(AsmTyper::VariableInfo::kImmutableGlobal);
var_info->set_standard_member(AsmTyper::kFFI);
AsmTyper::VariableInfo::ForSpecialSymbol(zone_, AsmTyper::kFFI);
CHECK(typer_->AddGlobal(var, var_info));
return this;
}
......@@ -911,6 +907,15 @@ TEST(ErrorsInExpression) {
} kTests[] = {
{"noy_a_function();", "Unanotated call to a function must be a call to"},
{"a = 0;", "Undeclared identifier"},
// we can't verify the module's name being referenced here because
// expression validation does not invoke ValidateModule, which sets up the
// module information in the AsmTyper.
{"stdlib", "accessed by ordinary expressions"},
{"ffi", "accessed by ordinary expressions"},
{"heap", "accessed by ordinary expressions"},
{"d2d", "accessed by ordinary expression"},
{"fround", "accessed by ordinary expression"},
{"d2s_tbl", "accessed by ordinary expression"},
{"ilocal = +1.0", "Type mismatch in assignment"},
{"!dlocal", "Invalid type for !"},
{"2 * dlocal", "Invalid types for intish *"},
......@@ -990,6 +995,9 @@ TEST(ErrorsInExpression) {
for (size_t ii = 0; ii < arraysize(kTests); ++ii) {
const auto* test = kTests + ii;
if (!ValidationOf(Expression(test->expression))
->WithStdlib(DynamicGlobal("stdlib"))
->WithFFI(DynamicGlobal("ffi"))
->WithHeap(DynamicGlobal("heap"))
->WithLocal(DynamicGlobal("iish"), iw::AsmType::Intish())
->WithLocal(DynamicGlobal("ilocal"), iw::AsmType::Int())
->WithLocal(DynamicGlobal("dlocal"), iw::AsmType::Double())
......@@ -1764,4 +1772,29 @@ TEST(ValidateCall) {
}
}
TEST(CannotReferenceModuleName) {
v8::V8::Initialize();
const struct {
const char* module;
const char* error_message;
} kTests[] = {
{"function asm() {\n"
" 'use asm';\n"
" function f() { asm; }\n"
"}",
"accessed by ordinary expressions"},
{"function asm() { 'use asm'; return asm; }", "Module cannot export"},
};
for (size_t ii = 0; ii < arraysize(kTests); ++ii) {
const auto* test = kTests + ii;
if (!ValidationOf(Module(test->module))
->FailsWithMessage(test->error_message)) {
std::cerr << "Test:\n" << test->module;
CHECK(false);
}
}
}
} // namespace
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