Revert "Revert "Upgrade to 5.0.71.48"" DO NOT MERGE
This reverts commit f2e3994fa5148cc3d9946666f0b0596290192b0e,
and updates the x64 makefile properly so it doesn't break that
build.
FPIIM-449
Change-Id: Ib83e35bfbae6af627451c926a9650ec57c045605
(cherry picked from commit 109988c7ccb6f3fd1a58574fa3dfb88beaef6632)
diff --git a/src/wasm/module-decoder.cc b/src/wasm/module-decoder.cc
index 24f3982..62b000d 100644
--- a/src/wasm/module-decoder.cc
+++ b/src/wasm/module-decoder.cc
@@ -54,6 +54,7 @@
module->functions = new std::vector<WasmFunction>();
module->data_segments = new std::vector<WasmDataSegment>();
module->function_table = new std::vector<uint16_t>();
+ module->import_table = new std::vector<WasmImport>();
bool sections[kMaxModuleSectionCode];
memset(sections, 0, sizeof(sections));
@@ -62,7 +63,7 @@
while (pc_ < limit_) {
TRACE("DecodeSection\n");
WasmSectionDeclCode section =
- static_cast<WasmSectionDeclCode>(u8("section"));
+ static_cast<WasmSectionDeclCode>(consume_u8("section"));
// Each section should appear at most once.
if (section < kMaxModuleSectionCode) {
CheckForPreviousSection(sections, section, false);
@@ -75,20 +76,20 @@
limit_ = pc_;
break;
case kDeclMemory:
- module->min_mem_size_log2 = u8("min memory");
- module->max_mem_size_log2 = u8("max memory");
- module->mem_export = u8("export memory") != 0;
+ module->min_mem_size_log2 = consume_u8("min memory");
+ module->max_mem_size_log2 = consume_u8("max memory");
+ module->mem_export = consume_u8("export memory") != 0;
break;
case kDeclSignatures: {
int length;
- uint32_t signatures_count = u32v(&length, "signatures count");
+ uint32_t signatures_count = consume_u32v(&length, "signatures count");
module->signatures->reserve(SafeReserve(signatures_count));
// Decode signatures.
for (uint32_t i = 0; i < signatures_count; i++) {
if (failed()) break;
TRACE("DecodeSignature[%d] module+%d\n", i,
static_cast<int>(pc_ - start_));
- FunctionSig* s = sig(); // read function sig.
+ FunctionSig* s = consume_sig(); // read function sig.
module->signatures->push_back(s);
}
break;
@@ -97,15 +98,12 @@
// Functions require a signature table first.
CheckForPreviousSection(sections, kDeclSignatures, true);
int length;
- uint32_t functions_count = u32v(&length, "functions count");
+ uint32_t functions_count = consume_u32v(&length, "functions count");
module->functions->reserve(SafeReserve(functions_count));
// Set up module environment for verification.
ModuleEnv menv;
menv.module = module;
- menv.globals_area = 0;
- menv.mem_start = 0;
- menv.mem_end = 0;
- menv.function_code = nullptr;
+ menv.instance = nullptr;
menv.asm_js = asm_js_;
// Decode functions.
for (uint32_t i = 0; i < functions_count; i++) {
@@ -114,7 +112,7 @@
static_cast<int>(pc_ - start_));
module->functions->push_back(
- {nullptr, 0, 0, 0, 0, 0, 0, false, false});
+ {nullptr, i, 0, 0, 0, 0, 0, 0, false, false});
WasmFunction* function = &module->functions->back();
DecodeFunctionInModule(module, function, false);
}
@@ -133,7 +131,7 @@
}
case kDeclGlobals: {
int length;
- uint32_t globals_count = u32v(&length, "globals count");
+ uint32_t globals_count = consume_u32v(&length, "globals count");
module->globals->reserve(SafeReserve(globals_count));
// Decode globals.
for (uint32_t i = 0; i < globals_count; i++) {
@@ -148,7 +146,8 @@
}
case kDeclDataSegments: {
int length;
- uint32_t data_segments_count = u32v(&length, "data segments count");
+ uint32_t data_segments_count =
+ consume_u32v(&length, "data segments count");
module->data_segments->reserve(SafeReserve(data_segments_count));
// Decode data segments.
for (uint32_t i = 0; i < data_segments_count; i++) {
@@ -157,7 +156,7 @@
static_cast<int>(pc_ - start_));
module->data_segments->push_back({0, 0, 0});
WasmDataSegment* segment = &module->data_segments->back();
- DecodeDataSegmentInModule(segment);
+ DecodeDataSegmentInModule(module, segment);
}
break;
}
@@ -165,14 +164,15 @@
// An indirect function table requires functions first.
CheckForPreviousSection(sections, kDeclFunctions, true);
int length;
- uint32_t function_table_count = u32v(&length, "function table count");
+ uint32_t function_table_count =
+ consume_u32v(&length, "function table count");
module->function_table->reserve(SafeReserve(function_table_count));
// Decode function table.
for (uint32_t i = 0; i < function_table_count; i++) {
if (failed()) break;
TRACE("DecodeFunctionTable[%d] module+%d\n", i,
static_cast<int>(pc_ - start_));
- uint16_t index = u16();
+ uint16_t index = consume_u16();
if (index >= module->functions->size()) {
error(pc_ - 2, "invalid function index");
break;
@@ -181,13 +181,66 @@
}
break;
}
+ case kDeclStartFunction: {
+ // Declares a start function for a module.
+ CheckForPreviousSection(sections, kDeclFunctions, true);
+ if (module->start_function_index >= 0) {
+ error("start function already declared");
+ break;
+ }
+ int length;
+ const byte* before = pc_;
+ uint32_t index = consume_u32v(&length, "start function index");
+ if (index >= module->functions->size()) {
+ error(before, "invalid start function index");
+ break;
+ }
+ module->start_function_index = static_cast<int>(index);
+ FunctionSig* sig =
+ module->signatures->at(module->functions->at(index).sig_index);
+ if (sig->parameter_count() > 0) {
+ error(before, "invalid start function: non-zero parameter count");
+ break;
+ }
+ break;
+ }
+ case kDeclImportTable: {
+ // Declares an import table.
+ CheckForPreviousSection(sections, kDeclSignatures, true);
+ int length;
+ uint32_t import_table_count =
+ consume_u32v(&length, "import table count");
+ module->import_table->reserve(SafeReserve(import_table_count));
+ // Decode import table.
+ for (uint32_t i = 0; i < import_table_count; i++) {
+ if (failed()) break;
+ TRACE("DecodeImportTable[%d] module+%d\n", i,
+ static_cast<int>(pc_ - start_));
+
+ module->import_table->push_back({nullptr, 0, 0});
+ WasmImport* import = &module->import_table->back();
+
+ const byte* sigpos = pc_;
+ import->sig_index = consume_u16("signature index");
+
+ if (import->sig_index >= module->signatures->size()) {
+ error(sigpos, "invalid signature index");
+ } else {
+ import->sig = module->signatures->at(import->sig_index);
+ }
+ import->module_name_offset = consume_string("import module name");
+ import->function_name_offset =
+ consume_string("import function name");
+ }
+ break;
+ }
case kDeclWLL: {
// Reserved for experimentation by the Web Low-level Language project
// which is augmenting the binary encoding with source code meta
// information. This section does not affect the semantics of the code
// and can be ignored by the runtime. https://github.com/JSStats/wll
int length = 0;
- uint32_t section_size = u32v(&length, "section size");
+ uint32_t section_size = consume_u32v(&length, "section size");
if (pc_ + section_size > limit_ || pc_ + section_size < pc_) {
error(pc_ - length, "invalid section size");
break;
@@ -249,14 +302,14 @@
FunctionResult DecodeSingleFunction(ModuleEnv* module_env,
WasmFunction* function) {
pc_ = start_;
- function->sig = sig(); // read signature
+ function->sig = consume_sig(); // read signature
function->name_offset = 0; // ---- name
function->code_start_offset = off(pc_ + 8); // ---- code start
function->code_end_offset = off(limit_); // ---- code end
- function->local_int32_count = u16(); // read u16
- function->local_int64_count = u16(); // read u16
- function->local_float32_count = u16(); // read u16
- function->local_float64_count = u16(); // read u16
+ function->local_i32_count = consume_u16(); // read u16
+ function->local_i64_count = consume_u16(); // read u16
+ function->local_f32_count = consume_u16(); // read u16
+ function->local_f64_count = consume_u16(); // read u16
function->exported = false; // ---- exported
function->external = false; // ---- external
@@ -271,7 +324,7 @@
// Decodes a single function signature at {start}.
FunctionSig* DecodeFunctionSignature(const byte* start) {
pc_ = start;
- FunctionSig* result = sig();
+ FunctionSig* result = consume_sig();
return ok() ? result : nullptr;
}
@@ -284,19 +337,19 @@
// Decodes a single global entry inside a module starting at {pc_}.
void DecodeGlobalInModule(WasmGlobal* global) {
- global->name_offset = string("global name");
+ global->name_offset = consume_string("global name");
global->type = mem_type();
global->offset = 0;
- global->exported = u8("exported") != 0;
+ global->exported = consume_u8("exported") != 0;
}
// Decodes a single function entry inside a module starting at {pc_}.
void DecodeFunctionInModule(WasmModule* module, WasmFunction* function,
bool verify_body = true) {
- byte decl_bits = u8("function decl");
+ byte decl_bits = consume_u8("function decl");
const byte* sigpos = pc_;
- function->sig_index = u16("signature index");
+ function->sig_index = consume_u16("signature index");
if (function->sig_index >= module->signatures->size()) {
return error(sigpos, "invalid signature index");
@@ -313,7 +366,7 @@
(decl_bits & kDeclFunctionImport) == 0 ? " body" : "");
if (decl_bits & kDeclFunctionName) {
- function->name_offset = string("function name");
+ function->name_offset = consume_string("function name");
}
function->exported = decl_bits & kDeclFunctionExport;
@@ -325,13 +378,13 @@
}
if (decl_bits & kDeclFunctionLocals) {
- function->local_int32_count = u16("int32 count");
- function->local_int64_count = u16("int64 count");
- function->local_float32_count = u16("float32 count");
- function->local_float64_count = u16("float64 count");
+ function->local_i32_count = consume_u16("i32 count");
+ function->local_i64_count = consume_u16("i64 count");
+ function->local_f32_count = consume_u16("f32 count");
+ function->local_f64_count = consume_u16("f64 count");
}
- uint16_t size = u16("body size");
+ uint16_t size = consume_u16("body size");
if (ok()) {
if ((pc_ + size) > limit_) {
return error(pc_, limit_,
@@ -345,35 +398,51 @@
}
}
+ bool IsWithinLimit(uint32_t limit, uint32_t offset, uint32_t size) {
+ if (offset > limit) return false;
+ if ((offset + size) < offset) return false; // overflow
+ return (offset + size) <= limit;
+ }
+
// Decodes a single data segment entry inside a module starting at {pc_}.
- void DecodeDataSegmentInModule(WasmDataSegment* segment) {
- segment->dest_addr =
- u32("destination"); // TODO(titzer): check it's within the memory size.
- segment->source_offset = offset("source offset");
- segment->source_size =
- u32("source size"); // TODO(titzer): check the size is reasonable.
- segment->init = u8("init");
+ void DecodeDataSegmentInModule(WasmModule* module, WasmDataSegment* segment) {
+ segment->dest_addr = consume_u32("destination");
+ segment->source_offset = consume_offset("source offset");
+ segment->source_size = consume_u32("source size");
+ segment->init = consume_u8("init");
+
+ // Validate the data is in the module.
+ uint32_t module_limit = static_cast<uint32_t>(limit_ - start_);
+ if (!IsWithinLimit(module_limit, segment->source_offset,
+ segment->source_size)) {
+ error(pc_ - sizeof(uint32_t), "segment out of bounds of module");
+ }
+
+ // Validate that the segment will fit into the (minimum) memory.
+ uint32_t memory_limit =
+ 1 << (module ? module->min_mem_size_log2 : WasmModule::kMaxMemSize);
+ if (!IsWithinLimit(memory_limit, segment->dest_addr,
+ segment->source_size)) {
+ error(pc_ - sizeof(uint32_t), "segment out of bounds of memory");
+ }
}
// Verifies the body (code) of a given function.
void VerifyFunctionBody(uint32_t func_num, ModuleEnv* menv,
WasmFunction* function) {
if (FLAG_trace_wasm_decode_time) {
- // TODO(titzer): clean me up a bit.
OFStream os(stdout);
- os << "Verifying WASM function:";
- if (function->name_offset > 0) {
- os << menv->module->GetName(function->name_offset);
- }
+ os << "Verifying WASM function " << WasmFunctionName(function, menv)
+ << std::endl;
os << std::endl;
}
FunctionEnv fenv;
fenv.module = menv;
fenv.sig = function->sig;
- fenv.local_int32_count = function->local_int32_count;
- fenv.local_int64_count = function->local_int64_count;
- fenv.local_float32_count = function->local_float32_count;
- fenv.local_float64_count = function->local_float64_count;
+ fenv.local_i32_count = function->local_i32_count;
+ fenv.local_i64_count = function->local_i64_count;
+ fenv.local_f32_count = function->local_f32_count;
+ fenv.local_f64_count = function->local_f64_count;
fenv.SumLocals();
TreeResult result =
@@ -382,8 +451,7 @@
if (result.failed()) {
// Wrap the error message from the function decoder.
std::ostringstream str;
- str << "in function #" << func_num << ": ";
- // TODO(titzer): add function name for the user?
+ str << "in function " << WasmFunctionName(function, menv) << ": ";
str << result;
std::string strval = str.str();
const char* raw = strval.c_str();
@@ -400,8 +468,8 @@
// Reads a single 32-bit unsigned integer interpreted as an offset, checking
// the offset is within bounds and advances.
- uint32_t offset(const char* name = nullptr) {
- uint32_t offset = u32(name ? name : "offset");
+ uint32_t consume_offset(const char* name = nullptr) {
+ uint32_t offset = consume_u32(name ? name : "offset");
if (offset > static_cast<uint32_t>(limit_ - start_)) {
error(pc_ - sizeof(uint32_t), "offset out of bounds of module");
}
@@ -410,13 +478,14 @@
// Reads a single 32-bit unsigned integer interpreted as an offset into the
// data and validating the string there and advances.
- uint32_t string(const char* name = nullptr) {
- return offset(name ? name : "string"); // TODO(titzer): validate string
+ uint32_t consume_string(const char* name = nullptr) {
+ // TODO(titzer): validate string
+ return consume_offset(name ? name : "string");
}
// Reads a single 8-bit integer, interpreting it as a local type.
- LocalType local_type() {
- byte val = u8("local type");
+ LocalType consume_local_type() {
+ byte val = consume_u8("local type");
LocalTypeCode t = static_cast<LocalTypeCode>(val);
switch (t) {
case kLocalVoid:
@@ -437,7 +506,7 @@
// Reads a single 8-bit integer, interpreting it as a memory type.
MachineType mem_type() {
- byte val = u8("memory type");
+ byte val = consume_u8("memory type");
MemTypeCode t = static_cast<MemTypeCode>(val);
switch (t) {
case kMemI8:
@@ -467,14 +536,14 @@
}
// Parses an inline function signature.
- FunctionSig* sig() {
- byte count = u8("param count");
- LocalType ret = local_type();
+ FunctionSig* consume_sig() {
+ byte count = consume_u8("param count");
+ LocalType ret = consume_local_type();
FunctionSig::Builder builder(module_zone, ret == kAstStmt ? 0 : 1, count);
if (ret != kAstStmt) builder.AddReturn(ret);
for (int i = 0; i < count; i++) {
- LocalType param = local_type();
+ LocalType param = consume_local_type();
if (param == kAstStmt) error(pc_ - 1, "invalid void parameter type");
builder.AddParam(param);
}