Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(8)

Side by Side Diff: src/wasm/module-decoder.cc

Issue 2361053004: Revert of [wasm] Master CL for Binary 0xC changes. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/wasm/module-decoder.h ('k') | src/wasm/wasm-debug.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/wasm/module-decoder.h" 5 #include "src/wasm/module-decoder.h"
6 6
7 #include "src/base/functional.h" 7 #include "src/base/functional.h"
8 #include "src/base/platform/platform.h" 8 #include "src/base/platform/platform.h"
9 #include "src/macro-assembler.h" 9 #include "src/macro-assembler.h"
10 #include "src/objects.h" 10 #include "src/objects.h"
11 #include "src/v8.h" 11 #include "src/v8.h"
12 12
13 #include "src/wasm/decoder.h" 13 #include "src/wasm/decoder.h"
14 14
15 namespace v8 { 15 namespace v8 {
16 namespace internal { 16 namespace internal {
17 namespace wasm { 17 namespace wasm {
18 18
19 #if DEBUG 19 #if DEBUG
20 #define TRACE(...) \ 20 #define TRACE(...) \
21 do { \ 21 do { \
22 if (FLAG_trace_wasm_decoder) PrintF(__VA_ARGS__); \ 22 if (FLAG_trace_wasm_decoder) PrintF(__VA_ARGS__); \
23 } while (false) 23 } while (false)
24 #else 24 #else
25 #define TRACE(...) 25 #define TRACE(...)
26 #endif 26 #endif
27 27
28 namespace { 28 namespace {
29 29
30 LocalType TypeOf(const WasmModule* module, const WasmInitExpr& expr) {
31 switch (expr.kind) {
32 case WasmInitExpr::kNone:
33 return kAstStmt;
34 case WasmInitExpr::kGlobalIndex:
35 return expr.val.global_index < module->globals.size()
36 ? module->globals[expr.val.global_index].type
37 : kAstStmt;
38 case WasmInitExpr::kI32Const:
39 return kAstI32;
40 case WasmInitExpr::kI64Const:
41 return kAstI64;
42 case WasmInitExpr::kF32Const:
43 return kAstF32;
44 case WasmInitExpr::kF64Const:
45 return kAstF64;
46 default:
47 UNREACHABLE();
48 return kAstStmt;
49 }
50 }
51
52 // An iterator over the sections in a WASM binary module.
53 // Automatically skips all unknown sections.
54 class WasmSectionIterator {
55 public:
56 explicit WasmSectionIterator(Decoder& decoder)
57 : decoder_(decoder),
58 section_code_(kUnknownSectionCode),
59 section_start_(decoder.pc()),
60 section_end_(decoder.pc()) {
61 next();
62 }
63
64 inline bool more() const {
65 return section_code_ != kUnknownSectionCode && decoder_.more();
66 }
67
68 inline WasmSectionCode section_code() const { return section_code_; }
69
70 inline const byte* section_start() const { return section_start_; }
71
72 inline uint32_t section_length() const {
73 return static_cast<uint32_t>(section_end_ - section_start_);
74 }
75
76 inline const byte* section_end() const { return section_end_; }
77
78 // Advances to the next section, checking that decoding the current section
79 // stopped at {section_end_}.
80 void advance() {
81 if (decoder_.pc() != section_end_) {
82 const char* msg = decoder_.pc() < section_end_ ? "shorter" : "longer";
83 decoder_.error(decoder_.pc(), decoder_.pc(),
84 "section was %s than expected size "
85 "(%u bytes expected, %zu decoded)",
86 msg, section_length(),
87 static_cast<size_t>(decoder_.pc() - section_start_));
88 }
89 next();
90 }
91
92 private:
93 Decoder& decoder_;
94 WasmSectionCode section_code_;
95 const byte* section_start_;
96 const byte* section_end_;
97
98 // Reads the section code/name at the current position and sets up
99 // the internal fields.
100 void next() {
101 while (true) {
102 if (!decoder_.more()) {
103 section_code_ = kUnknownSectionCode;
104 return;
105 }
106 uint8_t section_code = decoder_.consume_u8("section code");
107 // Read and check the section size.
108 uint32_t section_length = decoder_.consume_u32v("section length");
109 section_start_ = decoder_.pc();
110 if (decoder_.checkAvailable(section_length)) {
111 // Get the limit of the section within the module.
112 section_end_ = section_start_ + section_length;
113 } else {
114 // The section would extend beyond the end of the module.
115 section_end_ = section_start_;
116 }
117
118 if (section_code == kUnknownSectionCode) {
119 // Check for the known "names" section.
120 uint32_t string_length = decoder_.consume_u32v("section name length");
121 const byte* section_name_start = decoder_.pc();
122 decoder_.consume_bytes(string_length, "section name");
123 if (decoder_.failed() || decoder_.pc() > section_end_) {
124 TRACE("Section name of length %u couldn't be read\n", string_length);
125 section_code_ = kUnknownSectionCode;
126 return;
127 }
128
129 TRACE(" +%d section name : \"%.*s\"\n",
130 static_cast<int>(section_name_start - decoder_.start()),
131 string_length < 20 ? string_length : 20, section_name_start);
132
133 if (string_length == kNameStringLength &&
134 strncmp(reinterpret_cast<const char*>(section_name_start),
135 kNameString, kNameStringLength) == 0) {
136 section_code = kNameSectionCode;
137 } else {
138 section_code = kUnknownSectionCode;
139 }
140 } else if (!IsValidSectionCode(section_code)) {
141 decoder_.error(decoder_.pc(), decoder_.pc(),
142 "unknown section code #0x%02x", section_code);
143 section_code = kUnknownSectionCode;
144 }
145 section_code_ = static_cast<WasmSectionCode>(section_code);
146
147 TRACE("Section: %s\n", SectionName(section_code_));
148 if (section_code_ == kUnknownSectionCode &&
149 section_end_ > decoder_.pc()) {
150 // skip to the end of the unknown section.
151 uint32_t remaining =
152 static_cast<uint32_t>(section_end_ - decoder_.pc());
153 decoder_.consume_bytes(remaining, "section payload");
154 // fall through and continue to the next section.
155 } else {
156 return;
157 }
158 }
159 }
160 };
161
162 // The main logic for decoding the bytes of a module. 30 // The main logic for decoding the bytes of a module.
163 class ModuleDecoder : public Decoder { 31 class ModuleDecoder : public Decoder {
164 public: 32 public:
165 ModuleDecoder(Zone* zone, const byte* module_start, const byte* module_end, 33 ModuleDecoder(Zone* zone, const byte* module_start, const byte* module_end,
166 ModuleOrigin origin) 34 ModuleOrigin origin)
167 : Decoder(module_start, module_end), module_zone(zone), origin_(origin) { 35 : Decoder(module_start, module_end), module_zone(zone), origin_(origin) {
168 result_.start = start_; 36 result_.start = start_;
169 if (limit_ < start_) { 37 if (limit_ < start_) {
170 error(start_, "end is less than start"); 38 error(start_, "end is less than start");
171 limit_ = start_; 39 limit_ = start_;
(...skipping 30 matching lines...) Expand all
202 } 70 }
203 71
204 // Decodes an entire module. 72 // Decodes an entire module.
205 ModuleResult DecodeModule(WasmModule* module, bool verify_functions = true) { 73 ModuleResult DecodeModule(WasmModule* module, bool verify_functions = true) {
206 pc_ = start_; 74 pc_ = start_;
207 module->module_start = start_; 75 module->module_start = start_;
208 module->module_end = limit_; 76 module->module_end = limit_;
209 module->min_mem_pages = 0; 77 module->min_mem_pages = 0;
210 module->max_mem_pages = 0; 78 module->max_mem_pages = 0;
211 module->mem_export = false; 79 module->mem_export = false;
80 module->mem_external = false;
212 module->origin = origin_; 81 module->origin = origin_;
213 82
214 const byte* pos = pc_; 83 const byte* pos = pc_;
84 int current_order = 0;
215 uint32_t magic_word = consume_u32("wasm magic"); 85 uint32_t magic_word = consume_u32("wasm magic");
216 #define BYTES(x) (x & 0xff), (x >> 8) & 0xff, (x >> 16) & 0xff, (x >> 24) & 0xff 86 #define BYTES(x) (x & 0xff), (x >> 8) & 0xff, (x >> 16) & 0xff, (x >> 24) & 0xff
217 if (magic_word != kWasmMagic) { 87 if (magic_word != kWasmMagic) {
218 error(pos, pos, 88 error(pos, pos,
219 "expected magic word %02x %02x %02x %02x, " 89 "expected magic word %02x %02x %02x %02x, "
220 "found %02x %02x %02x %02x", 90 "found %02x %02x %02x %02x",
221 BYTES(kWasmMagic), BYTES(magic_word)); 91 BYTES(kWasmMagic), BYTES(magic_word));
92 goto done;
222 } 93 }
223 94
224 pos = pc_; 95 pos = pc_;
225 { 96 {
226 uint32_t magic_version = consume_u32("wasm version"); 97 uint32_t magic_version = consume_u32("wasm version");
227 if (magic_version != kWasmVersion) { 98 if (magic_version != kWasmVersion) {
228 error(pos, pos, 99 error(pos, pos,
229 "expected version %02x %02x %02x %02x, " 100 "expected version %02x %02x %02x %02x, "
230 "found %02x %02x %02x %02x", 101 "found %02x %02x %02x %02x",
231 BYTES(kWasmVersion), BYTES(magic_version)); 102 BYTES(kWasmVersion), BYTES(magic_version));
103 goto done;
232 } 104 }
233 } 105 }
234 106
235 WasmSectionIterator section_iter(*this); 107 // Decode the module sections.
236 108 while (pc_ < limit_) {
237 // ===== Type section ==================================================== 109 TRACE("DecodeSection\n");
238 if (section_iter.section_code() == kTypeSectionCode) { 110 pos = pc_;
239 uint32_t signatures_count = consume_u32v("signatures count"); 111
240 module->signatures.reserve(SafeReserve(signatures_count)); 112 // Read the section name.
241 for (uint32_t i = 0; ok() && i < signatures_count; ++i) { 113 uint32_t string_length = consume_u32v("section name length");
242 TRACE("DecodeSignature[%d] module+%d\n", i, 114 const byte* section_name_start = pc_;
243 static_cast<int>(pc_ - start_)); 115 consume_bytes(string_length);
244 FunctionSig* s = consume_sig(); 116 if (failed()) {
245 module->signatures.push_back(s); 117 TRACE("Section name of length %u couldn't be read\n", string_length);
246 } 118 break;
247 section_iter.advance(); 119 }
248 } 120
249 121 TRACE(" +%d section name : \"%.*s\"\n",
250 // ===== Import section ================================================== 122 static_cast<int>(section_name_start - start_),
251 if (section_iter.section_code() == kImportSectionCode) { 123 string_length < 20 ? string_length : 20, section_name_start);
252 uint32_t import_table_count = consume_u32v("import table count"); 124
253 module->import_table.reserve(SafeReserve(import_table_count)); 125 WasmSection::Code section =
254 for (uint32_t i = 0; ok() && i < import_table_count; ++i) { 126 WasmSection::lookup(section_name_start, string_length);
255 TRACE("DecodeImportTable[%d] module+%d\n", i, 127
256 static_cast<int>(pc_ - start_)); 128 // Read and check the section size.
257 129 uint32_t section_length = consume_u32v("section length");
258 module->import_table.push_back({ 130 if (!checkAvailable(section_length)) {
259 0, // module_name_length 131 // The section would extend beyond the end of the module.
260 0, // module_name_offset 132 break;
261 0, // field_name_offset 133 }
262 0, // field_name_length 134 const byte* section_start = pc_;
263 kExternalFunction, // kind 135 const byte* expected_section_end = pc_ + section_length;
264 0 // index 136
265 }); 137 current_order = CheckSectionOrder(current_order, section);
266 WasmImport* import = &module->import_table.back(); 138
267 const byte* pos = pc_; 139 switch (section) {
268 import->module_name_offset = 140 case WasmSection::Code::End:
269 consume_string(&import->module_name_length, true); 141 // Terminate section decoding.
270 if (import->module_name_length == 0) { 142 limit_ = pc_;
271 error(pos, "import module name cannot be NULL"); 143 break;
272 } 144 case WasmSection::Code::Memory: {
273 import->field_name_offset = 145 module->min_mem_pages = consume_u32v("min memory");
274 consume_string(&import->field_name_length, true); 146 module->max_mem_pages = consume_u32v("max memory");
275 147 module->mem_export = consume_u8("export memory") != 0;
276 import->kind = static_cast<WasmExternalKind>(consume_u8("import kind")); 148 break;
277 switch (import->kind) { 149 }
278 case kExternalFunction: { 150 case WasmSection::Code::Signatures: {
279 // ===== Imported function ======================================= 151 uint32_t signatures_count = consume_u32v("signatures count");
280 import->index = static_cast<uint32_t>(module->functions.size()); 152 module->signatures.reserve(SafeReserve(signatures_count));
281 module->num_imported_functions++; 153 // Decode signatures.
282 module->functions.push_back({nullptr, // sig 154 for (uint32_t i = 0; ok() && i < signatures_count; ++i) {
283 import->index, // func_index 155 TRACE("DecodeSignature[%d] module+%d\n", i,
284 0, // sig_index 156 static_cast<int>(pc_ - start_));
285 0, // name_offset 157 FunctionSig* s = consume_sig();
286 0, // name_length 158 module->signatures.push_back(s);
287 0, // code_start_offset 159 }
288 0, // code_end_offset 160 break;
289 true, // imported 161 }
290 false}); // exported 162 case WasmSection::Code::FunctionSignatures: {
163 uint32_t functions_count = consume_u32v("functions count");
164 module->functions.reserve(SafeReserve(functions_count));
165 for (uint32_t i = 0; ok() && i < functions_count; ++i) {
166 module->functions.push_back({nullptr, // sig
167 i, // func_index
168 0, // sig_index
169 0, // name_offset
170 0, // name_length
171 0, // code_start_offset
172 0}); // code_end_offset
291 WasmFunction* function = &module->functions.back(); 173 WasmFunction* function = &module->functions.back();
292 function->sig_index = consume_sig_index(module, &function->sig); 174 function->sig_index = consume_sig_index(module, &function->sig);
293 break; 175 }
294 } 176 break;
295 case kExternalTable: { 177 }
296 // ===== Imported table ========================================== 178 case WasmSection::Code::FunctionBodies: {
297 import->index = 179 const byte* pos = pc_;
298 static_cast<uint32_t>(module->function_tables.size()); 180 uint32_t functions_count = consume_u32v("functions count");
299 module->function_tables.push_back( 181 if (functions_count != module->functions.size()) {
300 {0, 0, std::vector<int32_t>(), true, false}); 182 error(pos, pos, "function body count %u mismatch (%u expected)",
301 expect_u8("element type", 0x20); 183 functions_count,
302 WasmIndirectFunctionTable* table = &module->function_tables.back(); 184 static_cast<uint32_t>(module->functions.size()));
303 consume_resizable_limits("element count", "elements", kMaxUInt32, 185 break;
304 &table->size, &table->max_size); 186 }
305 break; 187 for (uint32_t i = 0; ok() && i < functions_count; ++i) {
306 } 188 WasmFunction* function = &module->functions[i];
307 case kExternalMemory: { 189 uint32_t size = consume_u32v("body size");
308 // ===== Imported memory ========================================= 190 function->code_start_offset = pc_offset();
309 // import->index = 191 function->code_end_offset = pc_offset() + size;
310 // static_cast<uint32_t>(module->memories.size()); 192
311 // TODO(titzer): imported memories 193 TRACE(" +%d %-20s: (%d bytes)\n", pc_offset(), "function body",
312 break; 194 size);
313 } 195 pc_ += size;
314 case kExternalGlobal: { 196 if (pc_ > limit_) {
315 // ===== Imported global ========================================= 197 error(pc_, "function body extends beyond end of file");
316 import->index = static_cast<uint32_t>(module->globals.size()); 198 }
317 module->globals.push_back( 199 }
318 {kAstStmt, false, NO_INIT, 0, true, false}); 200 break;
201 }
202 case WasmSection::Code::Names: {
203 const byte* pos = pc_;
204 uint32_t functions_count = consume_u32v("functions count");
205 if (functions_count != module->functions.size()) {
206 error(pos, pos, "function name count %u mismatch (%u expected)",
207 functions_count,
208 static_cast<uint32_t>(module->functions.size()));
209 break;
210 }
211
212 for (uint32_t i = 0; ok() && i < functions_count; ++i) {
213 WasmFunction* function = &module->functions[i];
214 function->name_offset =
215 consume_string(&function->name_length, false);
216
217 uint32_t local_names_count = consume_u32v("local names count");
218 for (uint32_t j = 0; ok() && j < local_names_count; j++) {
219 uint32_t unused = 0;
220 uint32_t offset = consume_string(&unused, false);
221 USE(unused);
222 USE(offset);
223 }
224 }
225 break;
226 }
227 case WasmSection::Code::Globals: {
228 uint32_t globals_count = consume_u32v("globals count");
229 module->globals.reserve(SafeReserve(globals_count));
230 // Decode globals.
231 for (uint32_t i = 0; ok() && i < globals_count; ++i) {
232 TRACE("DecodeGlobal[%d] module+%d\n", i,
233 static_cast<int>(pc_ - start_));
234 // Add an uninitialized global and pass a pointer to it.
235 module->globals.push_back({0, 0, kAstStmt, 0, false});
319 WasmGlobal* global = &module->globals.back(); 236 WasmGlobal* global = &module->globals.back();
320 global->type = consume_value_type(); 237 DecodeGlobalInModule(global);
321 global->mutability = consume_u8("mutability") != 0; 238 }
322 break; 239 break;
323 } 240 }
324 default: 241 case WasmSection::Code::DataSegments: {
325 error(pos, pos, "unknown import kind 0x%02x", import->kind); 242 uint32_t data_segments_count = consume_u32v("data segments count");
326 break; 243 module->data_segments.reserve(SafeReserve(data_segments_count));
327 } 244 // Decode data segments.
328 } 245 for (uint32_t i = 0; ok() && i < data_segments_count; ++i) {
329 section_iter.advance(); 246 TRACE("DecodeDataSegment[%d] module+%d\n", i,
247 static_cast<int>(pc_ - start_));
248 module->data_segments.push_back({0, // dest_addr
249 0, // source_offset
250 0, // source_size
251 false}); // init
252 WasmDataSegment* segment = &module->data_segments.back();
253 DecodeDataSegmentInModule(module, segment);
254 }
255 break;
256 }
257 case WasmSection::Code::FunctionTable: {
258 // An indirect function table requires functions first.
259 CheckForFunctions(module, section);
260 // Assume only one table for now.
261 static const uint32_t kSupportedTableCount = 1;
262 module->function_tables.reserve(SafeReserve(kSupportedTableCount));
263 // Decode function table.
264 for (uint32_t i = 0; ok() && i < kSupportedTableCount; ++i) {
265 TRACE("DecodeFunctionTable[%d] module+%d\n", i,
266 static_cast<int>(pc_ - start_));
267 module->function_tables.push_back({0, 0, std::vector<uint16_t>()});
268 DecodeFunctionTableInModule(module, &module->function_tables[i]);
269 }
270 break;
271 }
272 case WasmSection::Code::StartFunction: {
273 // Declares a start function for a module.
274 CheckForFunctions(module, section);
275 if (module->start_function_index >= 0) {
276 error("start function already declared");
277 break;
278 }
279 WasmFunction* func;
280 const byte* pos = pc_;
281 module->start_function_index = consume_func_index(module, &func);
282 if (func && func->sig->parameter_count() > 0) {
283 error(pos, "invalid start function: non-zero parameter count");
284 break;
285 }
286 break;
287 }
288 case WasmSection::Code::ImportTable: {
289 uint32_t import_table_count = consume_u32v("import table count");
290 module->import_table.reserve(SafeReserve(import_table_count));
291 // Decode import table.
292 for (uint32_t i = 0; ok() && i < import_table_count; ++i) {
293 TRACE("DecodeImportTable[%d] module+%d\n", i,
294 static_cast<int>(pc_ - start_));
295
296 module->import_table.push_back({nullptr, // sig
297 0, // sig_index
298 0, // module_name_offset
299 0, // module_name_length
300 0, // function_name_offset
301 0}); // function_name_length
302 WasmImport* import = &module->import_table.back();
303
304 import->sig_index = consume_sig_index(module, &import->sig);
305 const byte* pos = pc_;
306 import->module_name_offset =
307 consume_string(&import->module_name_length, true);
308 if (import->module_name_length == 0) {
309 error(pos, "import module name cannot be NULL");
310 }
311 import->function_name_offset =
312 consume_string(&import->function_name_length, true);
313 }
314 break;
315 }
316 case WasmSection::Code::ExportTable: {
317 // Declares an export table.
318 CheckForFunctions(module, section);
319 uint32_t export_table_count = consume_u32v("export table count");
320 module->export_table.reserve(SafeReserve(export_table_count));
321 // Decode export table.
322 for (uint32_t i = 0; ok() && i < export_table_count; ++i) {
323 TRACE("DecodeExportTable[%d] module+%d\n", i,
324 static_cast<int>(pc_ - start_));
325
326 module->export_table.push_back({0, // func_index
327 0, // name_offset
328 0}); // name_length
329 WasmExport* exp = &module->export_table.back();
330
331 WasmFunction* func;
332 exp->func_index = consume_func_index(module, &func);
333 exp->name_offset = consume_string(&exp->name_length, true);
334 }
335 // Check for duplicate exports.
336 if (ok() && module->export_table.size() > 1) {
337 std::vector<WasmExport> sorted_exports(module->export_table);
338 const byte* base = start_;
339 auto cmp_less = [base](const WasmExport& a, const WasmExport& b) {
340 // Return true if a < b.
341 uint32_t len = a.name_length;
342 if (len != b.name_length) return len < b.name_length;
343 return memcmp(base + a.name_offset, base + b.name_offset, len) <
344 0;
345 };
346 std::stable_sort(sorted_exports.begin(), sorted_exports.end(),
347 cmp_less);
348 auto it = sorted_exports.begin();
349 WasmExport* last = &*it++;
350 for (auto end = sorted_exports.end(); it != end; last = &*it++) {
351 DCHECK(!cmp_less(*it, *last)); // Vector must be sorted.
352 if (!cmp_less(*last, *it)) {
353 const byte* pc = start_ + it->name_offset;
354 error(pc, pc,
355 "Duplicate export name '%.*s' for functions %d and %d",
356 it->name_length, pc, last->func_index, it->func_index);
357 break;
358 }
359 }
360 }
361 break;
362 }
363 case WasmSection::Code::Max:
364 // Skip unknown sections.
365 TRACE("Unknown section: '");
366 for (uint32_t i = 0; i != string_length; ++i) {
367 TRACE("%c", *(section_name_start + i));
368 }
369 TRACE("'\n");
370 consume_bytes(section_length);
371 break;
372 }
373
374 if (pc_ != expected_section_end) {
375 const char* diff = pc_ < expected_section_end ? "shorter" : "longer";
376 size_t expected_length = static_cast<size_t>(section_length);
377 size_t actual_length = static_cast<size_t>(pc_ - section_start);
378 error(pc_, pc_,
379 "section \"%s\" %s (%zu bytes) than specified (%zu bytes)",
380 WasmSection::getName(section), diff, actual_length,
381 expected_length);
382 break;
383 }
330 } 384 }
331 385
332 // ===== Function section ================================================ 386 done:
333 if (section_iter.section_code() == kFunctionSectionCode) { 387 if (ok()) CalculateGlobalsOffsets(module);
334 uint32_t functions_count = consume_u32v("functions count");
335 module->functions.reserve(SafeReserve(functions_count));
336 module->num_declared_functions = functions_count;
337 for (uint32_t i = 0; ok() && i < functions_count; ++i) {
338 uint32_t func_index = static_cast<uint32_t>(module->functions.size());
339 module->functions.push_back({nullptr, // sig
340 func_index, // func_index
341 0, // sig_index
342 0, // name_offset
343 0, // name_length
344 0, // code_start_offset
345 0, // code_end_offset
346 false, // imported
347 false}); // exported
348 WasmFunction* function = &module->functions.back();
349 function->sig_index = consume_sig_index(module, &function->sig);
350 }
351 section_iter.advance();
352 }
353
354 // ===== Table section ===================================================
355 if (section_iter.section_code() == kTableSectionCode) {
356 const byte* pos = pc_;
357 uint32_t table_count = consume_u32v("table count");
358 // Require at most one table for now.
359 if (table_count > 1) {
360 error(pos, pos, "invalid table count %d, maximum 1", table_count);
361 }
362
363 for (uint32_t i = 0; ok() && i < table_count; i++) {
364 module->function_tables.push_back(
365 {0, 0, std::vector<int32_t>(), false, false});
366 WasmIndirectFunctionTable* table = &module->function_tables.back();
367 expect_u8("table type", kWasmAnyFunctionTypeForm);
368 consume_resizable_limits("table elements", "elements", kMaxUInt32,
369 &table->size, &table->max_size);
370 }
371 section_iter.advance();
372 }
373
374 // ===== Memory section ==================================================
375 if (section_iter.section_code() == kMemorySectionCode) {
376 const byte* pos = pc_;
377 uint32_t memory_count = consume_u32v("memory count");
378 // Require at most one memory for now.
379 if (memory_count > 1) {
380 error(pos, pos, "invalid memory count %d, maximum 1", memory_count);
381 }
382
383 for (uint32_t i = 0; ok() && i < memory_count; i++) {
384 consume_resizable_limits("memory", "pages", WasmModule::kMaxLegalPages,
385 &module->min_mem_pages,
386 &module->max_mem_pages);
387 }
388 section_iter.advance();
389 }
390
391 // ===== Global section ==================================================
392 if (section_iter.section_code() == kGlobalSectionCode) {
393 uint32_t globals_count = consume_u32v("globals count");
394 module->globals.reserve(SafeReserve(globals_count));
395 for (uint32_t i = 0; ok() && i < globals_count; ++i) {
396 TRACE("DecodeGlobal[%d] module+%d\n", i,
397 static_cast<int>(pc_ - start_));
398 // Add an uninitialized global and pass a pointer to it.
399 module->globals.push_back({kAstStmt, false, NO_INIT, 0, false, false});
400 WasmGlobal* global = &module->globals.back();
401 DecodeGlobalInModule(module, i, global);
402 }
403 section_iter.advance();
404 }
405
406 // ===== Export section ==================================================
407 if (section_iter.section_code() == kExportSectionCode) {
408 uint32_t export_table_count = consume_u32v("export table count");
409 module->export_table.reserve(SafeReserve(export_table_count));
410 for (uint32_t i = 0; ok() && i < export_table_count; ++i) {
411 TRACE("DecodeExportTable[%d] module+%d\n", i,
412 static_cast<int>(pc_ - start_));
413
414 module->export_table.push_back({
415 0, // name_length
416 0, // name_offset
417 kExternalFunction, // kind
418 0 // index
419 });
420 WasmExport* exp = &module->export_table.back();
421
422 exp->name_offset = consume_string(&exp->name_length, true);
423 const byte* pos = pc();
424 exp->kind = static_cast<WasmExternalKind>(consume_u8("export kind"));
425 switch (exp->kind) {
426 case kExternalFunction: {
427 WasmFunction* func = nullptr;
428 exp->index = consume_func_index(module, &func);
429 module->num_exported_functions++;
430 if (func) func->exported = true;
431 break;
432 }
433 case kExternalTable: {
434 WasmIndirectFunctionTable* table = nullptr;
435 exp->index = consume_table_index(module, &table);
436 if (table) table->exported = true;
437 break;
438 }
439 case kExternalMemory: {
440 uint32_t index = consume_u32v("memory index");
441 if (index != 0) error("invalid memory index != 0");
442 module->mem_export = true;
443 break;
444 }
445 case kExternalGlobal: {
446 WasmGlobal* global = nullptr;
447 exp->index = consume_global_index(module, &global);
448 if (global) global->exported = true;
449 break;
450 }
451 default:
452 error(pos, pos, "invalid export kind 0x%02x", exp->kind);
453 break;
454 }
455 }
456 // Check for duplicate exports.
457 if (ok() && module->export_table.size() > 1) {
458 std::vector<WasmExport> sorted_exports(module->export_table);
459 const byte* base = start_;
460 auto cmp_less = [base](const WasmExport& a, const WasmExport& b) {
461 // Return true if a < b.
462 if (a.name_length != b.name_length) {
463 return a.name_length < b.name_length;
464 }
465 return memcmp(base + a.name_offset, base + b.name_offset,
466 a.name_length) < 0;
467 };
468 std::stable_sort(sorted_exports.begin(), sorted_exports.end(),
469 cmp_less);
470 auto it = sorted_exports.begin();
471 WasmExport* last = &*it++;
472 for (auto end = sorted_exports.end(); it != end; last = &*it++) {
473 DCHECK(!cmp_less(*it, *last)); // Vector must be sorted.
474 if (!cmp_less(*last, *it)) {
475 const byte* pc = start_ + it->name_offset;
476 error(pc, pc,
477 "Duplicate export name '%.*s' for functions %d and %d",
478 it->name_length, pc, last->index, it->index);
479 break;
480 }
481 }
482 }
483 section_iter.advance();
484 }
485
486 // ===== Start section ===================================================
487 if (section_iter.section_code() == kStartSectionCode) {
488 WasmFunction* func;
489 const byte* pos = pc_;
490 module->start_function_index = consume_func_index(module, &func);
491 if (func && func->sig->parameter_count() > 0) {
492 error(pos, "invalid start function: non-zero parameter count");
493 }
494 section_iter.advance();
495 }
496
497 // ===== Elements section ================================================
498 if (section_iter.section_code() == kElementSectionCode) {
499 uint32_t element_count = consume_u32v("element count");
500 for (uint32_t i = 0; ok() && i < element_count; ++i) {
501 uint32_t table_index = consume_u32v("table index");
502 if (table_index != 0) error("illegal table index != 0");
503 WasmInitExpr offset = consume_init_expr(module, kAstI32);
504 uint32_t num_elem = consume_u32v("number of elements");
505 std::vector<uint32_t> vector;
506 module->table_inits.push_back({table_index, offset, vector});
507 WasmTableInit* init = &module->table_inits.back();
508 init->entries.reserve(SafeReserve(num_elem));
509 for (uint32_t j = 0; ok() && j < num_elem; j++) {
510 WasmFunction* func = nullptr;
511 init->entries.push_back(consume_func_index(module, &func));
512 }
513 }
514
515 section_iter.advance();
516 }
517
518 // ===== Code section ====================================================
519 if (section_iter.section_code() == kCodeSectionCode) {
520 const byte* pos = pc_;
521 uint32_t functions_count = consume_u32v("functions count");
522 if (functions_count != module->num_declared_functions) {
523 error(pos, pos, "function body count %u mismatch (%u expected)",
524 functions_count, module->num_declared_functions);
525 }
526 for (uint32_t i = 0; ok() && i < functions_count; ++i) {
527 WasmFunction* function =
528 &module->functions[i + module->num_imported_functions];
529 uint32_t size = consume_u32v("body size");
530 function->code_start_offset = pc_offset();
531 function->code_end_offset = pc_offset() + size;
532 consume_bytes(size, "function body");
533 }
534 section_iter.advance();
535 }
536
537 // ===== Data section ====================================================
538 if (section_iter.section_code() == kDataSectionCode) {
539 uint32_t data_segments_count = consume_u32v("data segments count");
540 module->data_segments.reserve(SafeReserve(data_segments_count));
541 for (uint32_t i = 0; ok() && i < data_segments_count; ++i) {
542 TRACE("DecodeDataSegment[%d] module+%d\n", i,
543 static_cast<int>(pc_ - start_));
544 module->data_segments.push_back({
545 NO_INIT, // dest_addr
546 0, // source_offset
547 0 // source_size
548 });
549 WasmDataSegment* segment = &module->data_segments.back();
550 DecodeDataSegmentInModule(module, segment);
551 }
552 section_iter.advance();
553 }
554
555 // ===== Name section ====================================================
556 if (section_iter.section_code() == kNameSectionCode) {
557 const byte* pos = pc_;
558 uint32_t functions_count = consume_u32v("functions count");
559 if (functions_count != module->num_declared_functions) {
560 error(pos, pos, "function name count %u mismatch (%u expected)",
561 functions_count, module->num_declared_functions);
562 }
563
564 for (uint32_t i = 0; ok() && i < functions_count; ++i) {
565 WasmFunction* function =
566 &module->functions[i + module->num_imported_functions];
567 function->name_offset = consume_string(&function->name_length, false);
568
569 uint32_t local_names_count = consume_u32v("local names count");
570 for (uint32_t j = 0; ok() && j < local_names_count; j++) {
571 uint32_t unused = 0;
572 uint32_t offset = consume_string(&unused, false);
573 USE(unused);
574 USE(offset);
575 }
576 }
577 section_iter.advance();
578 }
579
580 // ===== Remaining sections ==============================================
581 if (section_iter.more() && ok()) {
582 error(pc(), pc(), "unexpected section: %s",
583 SectionName(section_iter.section_code()));
584 }
585
586 if (ok()) {
587 CalculateGlobalOffsets(module);
588 PreinitializeIndirectFunctionTables(module);
589 }
590 const WasmModule* finished_module = module; 388 const WasmModule* finished_module = module;
591 ModuleResult result = toResult(finished_module); 389 ModuleResult result = toResult(finished_module);
592 if (FLAG_dump_wasm_module) DumpModule(module, result); 390 if (FLAG_dump_wasm_module) {
391 DumpModule(module, result);
392 }
593 return result; 393 return result;
594 } 394 }
595 395
596 uint32_t SafeReserve(uint32_t count) { 396 uint32_t SafeReserve(uint32_t count) {
597 // Avoid OOM by only reserving up to a certain size. 397 // Avoid OOM by only reserving up to a certain size.
598 const uint32_t kMaxReserve = 20000; 398 const uint32_t kMaxReserve = 20000;
599 return count < kMaxReserve ? count : kMaxReserve; 399 return count < kMaxReserve ? count : kMaxReserve;
600 } 400 }
601 401
402 void CheckForFunctions(WasmModule* module, WasmSection::Code section) {
403 if (module->functions.size() == 0) {
404 error(pc_ - 1, nullptr, "functions must appear before section %s",
405 WasmSection::getName(section));
406 }
407 }
408
409 int CheckSectionOrder(int current_order, WasmSection::Code section) {
410 int next_order = WasmSection::getOrder(section);
411 if (next_order == 0) return current_order;
412 if (next_order == current_order) {
413 error(pc_, pc_, "section \"%s\" already defined",
414 WasmSection::getName(section));
415 }
416 if (next_order < current_order) {
417 error(pc_, pc_, "section \"%s\" out of order",
418 WasmSection::getName(section));
419 }
420 return next_order;
421 }
422
602 // Decodes a single anonymous function starting at {start_}. 423 // Decodes a single anonymous function starting at {start_}.
603 FunctionResult DecodeSingleFunction(ModuleEnv* module_env, 424 FunctionResult DecodeSingleFunction(ModuleEnv* module_env,
604 WasmFunction* function) { 425 WasmFunction* function) {
605 pc_ = start_; 426 pc_ = start_;
606 function->sig = consume_sig(); // read signature 427 function->sig = consume_sig(); // read signature
607 function->name_offset = 0; // ---- name 428 function->name_offset = 0; // ---- name
608 function->name_length = 0; // ---- name length 429 function->name_length = 0; // ---- name length
609 function->code_start_offset = off(pc_); // ---- code start 430 function->code_start_offset = off(pc_); // ---- code start
610 function->code_end_offset = off(limit_); // ---- code end 431 function->code_end_offset = off(limit_); // ---- code end
611 432
612 if (ok()) VerifyFunctionBody(0, module_env, function); 433 if (ok()) VerifyFunctionBody(0, module_env, function);
613 434
614 FunctionResult result; 435 FunctionResult result;
615 result.MoveFrom(result_); // Copy error code and location. 436 result.MoveFrom(result_); // Copy error code and location.
616 result.val = function; 437 result.val = function;
617 return result; 438 return result;
618 } 439 }
619 440
620 // Decodes a single function signature at {start}. 441 // Decodes a single function signature at {start}.
621 FunctionSig* DecodeFunctionSignature(const byte* start) { 442 FunctionSig* DecodeFunctionSignature(const byte* start) {
622 pc_ = start; 443 pc_ = start;
623 FunctionSig* result = consume_sig(); 444 FunctionSig* result = consume_sig();
624 return ok() ? result : nullptr; 445 return ok() ? result : nullptr;
625 } 446 }
626 447
627 WasmInitExpr DecodeInitExpr(const byte* start) {
628 pc_ = start;
629 return consume_init_expr(nullptr, kAstStmt);
630 }
631
632 private: 448 private:
633 Zone* module_zone; 449 Zone* module_zone;
634 ModuleResult result_; 450 ModuleResult result_;
635 ModuleOrigin origin_; 451 ModuleOrigin origin_;
636 452
637 uint32_t off(const byte* ptr) { return static_cast<uint32_t>(ptr - start_); } 453 uint32_t off(const byte* ptr) { return static_cast<uint32_t>(ptr - start_); }
638 454
639 // Decodes a single global entry inside a module starting at {pc_}. 455 // Decodes a single global entry inside a module starting at {pc_}.
640 void DecodeGlobalInModule(WasmModule* module, uint32_t index, 456 void DecodeGlobalInModule(WasmGlobal* global) {
641 WasmGlobal* global) { 457 global->name_offset = consume_string(&global->name_length, false);
642 global->type = consume_value_type(); 458 if (ok() &&
643 global->mutability = consume_u8("mutability") != 0; 459 !unibrow::Utf8::Validate(start_ + global->name_offset,
644 const byte* pos = pc(); 460 global->name_length)) {
645 global->init = consume_init_expr(module, kAstStmt); 461 error("global name is not valid utf8");
646 switch (global->init.kind) {
647 case WasmInitExpr::kGlobalIndex:
648 if (global->init.val.global_index >= index) {
649 error("invalid global index in init expression");
650 } else if (module->globals[index].type != global->type) {
651 error("type mismatch in global initialization");
652 }
653 break;
654 default:
655 if (global->type != TypeOf(module, global->init)) {
656 error(pos, pos,
657 "type error in global initialization, expected %s, got %s",
658 WasmOpcodes::TypeName(global->type),
659 WasmOpcodes::TypeName(TypeOf(module, global->init)));
660 }
661 } 462 }
463 global->type = consume_local_type();
464 if (global->type == kAstStmt) {
465 error("invalid global type");
466 }
467 global->offset = 0;
468 global->exported = consume_u8("exported") != 0;
662 } 469 }
663 470
664 bool IsWithinLimit(uint32_t limit, uint32_t offset, uint32_t size) { 471 bool IsWithinLimit(uint32_t limit, uint32_t offset, uint32_t size) {
665 if (offset > limit) return false; 472 if (offset > limit) return false;
666 if ((offset + size) < offset) return false; // overflow 473 if ((offset + size) < offset) return false; // overflow
667 return (offset + size) <= limit; 474 return (offset + size) <= limit;
668 } 475 }
669 476
670 // Decodes a single data segment entry inside a module starting at {pc_}. 477 // Decodes a single data segment entry inside a module starting at {pc_}.
671 void DecodeDataSegmentInModule(WasmModule* module, WasmDataSegment* segment) { 478 void DecodeDataSegmentInModule(WasmModule* module, WasmDataSegment* segment) {
672 const byte* start = pc_; 479 const byte* start = pc_;
673 expect_u8("linear memory index", 0); 480 segment->dest_addr = consume_u32v("destination");
674 segment->dest_addr = consume_init_expr(module, kAstI32);
675 segment->source_size = consume_u32v("source size"); 481 segment->source_size = consume_u32v("source size");
676 segment->source_offset = static_cast<uint32_t>(pc_ - start_); 482 segment->source_offset = static_cast<uint32_t>(pc_ - start_);
483 segment->init = true;
677 484
678 // Validate the data is in the module. 485 // Validate the data is in the module.
679 uint32_t module_limit = static_cast<uint32_t>(limit_ - start_); 486 uint32_t module_limit = static_cast<uint32_t>(limit_ - start_);
680 if (!IsWithinLimit(module_limit, segment->source_offset, 487 if (!IsWithinLimit(module_limit, segment->source_offset,
681 segment->source_size)) { 488 segment->source_size)) {
682 error(start, "segment out of bounds of module"); 489 error(start, "segment out of bounds of module");
683 } 490 }
684 491
685 consume_bytes(segment->source_size, "segment data"); 492 // Validate that the segment will fit into the (minimum) memory.
493 uint32_t memory_limit =
494 WasmModule::kPageSize * (module ? module->min_mem_pages
495 : WasmModule::kMaxMemPages);
496 if (!IsWithinLimit(memory_limit, segment->dest_addr,
497 segment->source_size)) {
498 error(start, "segment out of bounds of memory");
499 }
500
501 consume_bytes(segment->source_size);
502 }
503
504 // Decodes a single function table inside a module starting at {pc_}.
505 void DecodeFunctionTableInModule(WasmModule* module,
506 WasmIndirectFunctionTable* table) {
507 table->size = consume_u32v("function table entry count");
508 table->max_size = table->size;
509
510 if (table->max_size != table->size) {
511 error("invalid table maximum size");
512 }
513
514 for (uint32_t i = 0; ok() && i < table->size; ++i) {
515 uint16_t index = consume_u32v();
516 if (index >= module->functions.size()) {
517 error(pc_ - sizeof(index), "invalid function index");
518 break;
519 }
520 table->values.push_back(index);
521 }
686 } 522 }
687 523
688 // Calculate individual global offsets and total size of globals table. 524 // Calculate individual global offsets and total size of globals table.
689 void CalculateGlobalOffsets(WasmModule* module) { 525 void CalculateGlobalsOffsets(WasmModule* module) {
690 uint32_t offset = 0; 526 uint32_t offset = 0;
691 if (module->globals.size() == 0) { 527 if (module->globals.size() == 0) {
692 module->globals_size = 0; 528 module->globals_size = 0;
693 return; 529 return;
694 } 530 }
695 for (WasmGlobal& global : module->globals) { 531 for (WasmGlobal& global : module->globals) {
696 byte size = 532 byte size =
697 WasmOpcodes::MemSize(WasmOpcodes::MachineTypeFor(global.type)); 533 WasmOpcodes::MemSize(WasmOpcodes::MachineTypeFor(global.type));
698 offset = (offset + size - 1) & ~(size - 1); // align 534 offset = (offset + size - 1) & ~(size - 1); // align
699 global.offset = offset; 535 global.offset = offset;
700 offset += size; 536 offset += size;
701 } 537 }
702 module->globals_size = offset; 538 module->globals_size = offset;
703 } 539 }
704 540
705 // TODO(titzer): this only works without overlapping initializations from
706 // global bases for entries
707 void PreinitializeIndirectFunctionTables(WasmModule* module) {
708 // Fill all tables with invalid entries first.
709 for (WasmIndirectFunctionTable& table : module->function_tables) {
710 table.values.resize(table.size);
711 for (size_t i = 0; i < table.size; i++) {
712 table.values[i] = kInvalidFunctionIndex;
713 }
714 }
715 for (WasmTableInit& init : module->table_inits) {
716 if (init.offset.kind != WasmInitExpr::kI32Const) continue;
717 if (init.table_index >= module->function_tables.size()) continue;
718 WasmIndirectFunctionTable& table =
719 module->function_tables[init.table_index];
720 for (size_t i = 0; i < init.entries.size(); i++) {
721 size_t index = i + init.offset.val.i32_const;
722 if (index < table.values.size()) {
723 table.values[index] = init.entries[i];
724 }
725 }
726 }
727 }
728
729 // Verifies the body (code) of a given function. 541 // Verifies the body (code) of a given function.
730 void VerifyFunctionBody(uint32_t func_num, ModuleEnv* menv, 542 void VerifyFunctionBody(uint32_t func_num, ModuleEnv* menv,
731 WasmFunction* function) { 543 WasmFunction* function) {
732 if (FLAG_trace_wasm_decoder || FLAG_trace_wasm_decode_time) { 544 if (FLAG_trace_wasm_decoder || FLAG_trace_wasm_decode_time) {
733 OFStream os(stdout); 545 OFStream os(stdout);
734 os << "Verifying WASM function " << WasmFunctionName(function, menv) 546 os << "Verifying WASM function " << WasmFunctionName(function, menv)
735 << std::endl; 547 << std::endl;
736 } 548 }
737 FunctionBody body = {menv, function->sig, start_, 549 FunctionBody body = {menv, function->sig, start_,
738 start_ + function->code_start_offset, 550 start_ + function->code_start_offset,
(...skipping 10 matching lines...) Expand all
749 char* buffer = new char[len]; 561 char* buffer = new char[len];
750 strncpy(buffer, raw, len); 562 strncpy(buffer, raw, len);
751 buffer[len - 1] = 0; 563 buffer[len - 1] = 0;
752 564
753 // Copy error code and location. 565 // Copy error code and location.
754 result_.MoveFrom(result); 566 result_.MoveFrom(result);
755 result_.error_msg.reset(buffer); 567 result_.error_msg.reset(buffer);
756 } 568 }
757 } 569 }
758 570
571 // Reads a single 32-bit unsigned integer interpreted as an offset, checking
572 // the offset is within bounds and advances.
573 uint32_t consume_offset(const char* name = nullptr) {
574 uint32_t offset = consume_u32(name ? name : "offset");
575 if (offset > static_cast<uint32_t>(limit_ - start_)) {
576 error(pc_ - sizeof(uint32_t), "offset out of bounds of module");
577 }
578 return offset;
579 }
580
759 // Reads a length-prefixed string, checking that it is within bounds. Returns 581 // Reads a length-prefixed string, checking that it is within bounds. Returns
760 // the offset of the string, and the length as an out parameter. 582 // the offset of the string, and the length as an out parameter.
761 uint32_t consume_string(uint32_t* length, bool validate_utf8) { 583 uint32_t consume_string(uint32_t* length, bool validate_utf8) {
762 *length = consume_u32v("string length"); 584 *length = consume_u32v("string length");
763 uint32_t offset = pc_offset(); 585 uint32_t offset = pc_offset();
586 TRACE(" +%u %-20s: (%u bytes)\n", offset, "string", *length);
764 const byte* string_start = pc_; 587 const byte* string_start = pc_;
765 // Consume bytes before validation to guarantee that the string is not oob. 588 // Consume bytes before validation to guarantee that the string is not oob.
766 consume_bytes(*length, "string"); 589 consume_bytes(*length);
767 if (ok() && validate_utf8 && 590 if (ok() && validate_utf8 &&
768 !unibrow::Utf8::Validate(string_start, *length)) { 591 !unibrow::Utf8::Validate(string_start, *length)) {
769 error(string_start, "no valid UTF-8 string"); 592 error(string_start, "no valid UTF-8 string");
770 } 593 }
771 return offset; 594 return offset;
772 } 595 }
773 596
774 uint32_t consume_sig_index(WasmModule* module, FunctionSig** sig) { 597 uint32_t consume_sig_index(WasmModule* module, FunctionSig** sig) {
775 const byte* pos = pc_; 598 const byte* pos = pc_;
776 uint32_t sig_index = consume_u32v("signature index"); 599 uint32_t sig_index = consume_u32v("signature index");
777 if (sig_index >= module->signatures.size()) { 600 if (sig_index >= module->signatures.size()) {
778 error(pos, pos, "signature index %u out of bounds (%d signatures)", 601 error(pos, pos, "signature index %u out of bounds (%d signatures)",
779 sig_index, static_cast<int>(module->signatures.size())); 602 sig_index, static_cast<int>(module->signatures.size()));
780 *sig = nullptr; 603 *sig = nullptr;
781 return 0; 604 return 0;
782 } 605 }
783 *sig = module->signatures[sig_index]; 606 *sig = module->signatures[sig_index];
784 return sig_index; 607 return sig_index;
785 } 608 }
786 609
787 uint32_t consume_func_index(WasmModule* module, WasmFunction** func) { 610 uint32_t consume_func_index(WasmModule* module, WasmFunction** func) {
788 return consume_index("function index", module->functions, func);
789 }
790
791 uint32_t consume_global_index(WasmModule* module, WasmGlobal** global) {
792 return consume_index("global index", module->globals, global);
793 }
794
795 uint32_t consume_table_index(WasmModule* module,
796 WasmIndirectFunctionTable** table) {
797 return consume_index("table index", module->function_tables, table);
798 }
799
800 template <typename T>
801 uint32_t consume_index(const char* name, std::vector<T>& vector, T** ptr) {
802 const byte* pos = pc_; 611 const byte* pos = pc_;
803 uint32_t index = consume_u32v(name); 612 uint32_t func_index = consume_u32v("function index");
804 if (index >= vector.size()) { 613 if (func_index >= module->functions.size()) {
805 error(pos, pos, "%s %u out of bounds (%d entries)", name, index, 614 error(pos, pos, "function index %u out of bounds (%d functions)",
806 static_cast<int>(vector.size())); 615 func_index, static_cast<int>(module->functions.size()));
807 *ptr = nullptr; 616 *func = nullptr;
808 return 0; 617 return 0;
809 } 618 }
810 *ptr = &vector[index]; 619 *func = &module->functions[func_index];
811 return index; 620 return func_index;
812 }
813
814 void consume_resizable_limits(const char* name, const char* units,
815 uint32_t max_value, uint32_t* initial,
816 uint32_t* maximum) {
817 uint32_t flags = consume_u32v("resizable limits flags");
818 const byte* pos = pc();
819 *initial = consume_u32v("initial size");
820 if (*initial > max_value) {
821 error(pos, pos,
822 "initial %s size (%u %s) is larger than maximum allowable (%u)",
823 name, *initial, units, max_value);
824 }
825 if (flags & 1) {
826 pos = pc();
827 *maximum = consume_u32v("maximum size");
828 if (*maximum > max_value) {
829 error(pos, pos,
830 "maximum %s size (%u %s) is larger than maximum allowable (%u)",
831 name, *maximum, units, max_value);
832 }
833 if (*maximum < *initial) {
834 error(pos, pos, "maximum %s size (%u %s) is less than initial (%u %s)",
835 name, *maximum, units, *initial, units);
836 }
837 } else {
838 *maximum = 0;
839 }
840 }
841
842 bool expect_u8(const char* name, uint8_t expected) {
843 const byte* pos = pc();
844 uint8_t value = consume_u8(name);
845 if (value != expected) {
846 error(pos, pos, "expected %s 0x%02x, got 0x%02x", name, expected, value);
847 return false;
848 }
849 return true;
850 }
851
852 WasmInitExpr consume_init_expr(WasmModule* module, LocalType expected) {
853 const byte* pos = pc();
854 uint8_t opcode = consume_u8("opcode");
855 WasmInitExpr expr;
856 unsigned len = 0;
857 switch (opcode) {
858 case kExprGetGlobal: {
859 GlobalIndexOperand operand(this, pc() - 1);
860 expr.kind = WasmInitExpr::kGlobalIndex;
861 expr.val.global_index = operand.index;
862 len = operand.length;
863 break;
864 }
865 case kExprI32Const: {
866 ImmI32Operand operand(this, pc() - 1);
867 expr.kind = WasmInitExpr::kI32Const;
868 expr.val.i32_const = operand.value;
869 len = operand.length;
870 break;
871 }
872 case kExprF32Const: {
873 ImmF32Operand operand(this, pc() - 1);
874 expr.kind = WasmInitExpr::kF32Const;
875 expr.val.f32_const = operand.value;
876 len = operand.length;
877 break;
878 }
879 case kExprI64Const: {
880 ImmI64Operand operand(this, pc() - 1);
881 expr.kind = WasmInitExpr::kI64Const;
882 expr.val.i64_const = operand.value;
883 len = operand.length;
884 break;
885 }
886 case kExprF64Const: {
887 ImmF64Operand operand(this, pc() - 1);
888 expr.kind = WasmInitExpr::kF64Const;
889 expr.val.f64_const = operand.value;
890 len = operand.length;
891 break;
892 }
893 default: {
894 error("invalid opcode in initialization expression");
895 expr.kind = WasmInitExpr::kNone;
896 expr.val.i32_const = 0;
897 }
898 }
899 consume_bytes(len, "init code");
900 if (!expect_u8("end opcode", kExprEnd)) {
901 expr.kind = WasmInitExpr::kNone;
902 }
903 if (expected != kAstStmt && TypeOf(module, expr) != kAstI32) {
904 error(pos, pos, "type error in init expression, expected %s, got %s",
905 WasmOpcodes::TypeName(expected),
906 WasmOpcodes::TypeName(TypeOf(module, expr)));
907 }
908 return expr;
909 } 621 }
910 622
911 // Reads a single 8-bit integer, interpreting it as a local type. 623 // Reads a single 8-bit integer, interpreting it as a local type.
912 LocalType consume_value_type() { 624 LocalType consume_local_type() {
913 byte val = consume_u8("value type"); 625 byte val = consume_u8("local type");
914 LocalTypeCode t = static_cast<LocalTypeCode>(val); 626 LocalTypeCode t = static_cast<LocalTypeCode>(val);
915 switch (t) { 627 switch (t) {
628 case kLocalVoid:
629 return kAstStmt;
916 case kLocalI32: 630 case kLocalI32:
917 return kAstI32; 631 return kAstI32;
918 case kLocalI64: 632 case kLocalI64:
919 return kAstI64; 633 return kAstI64;
920 case kLocalF32: 634 case kLocalF32:
921 return kAstF32; 635 return kAstF32;
922 case kLocalF64: 636 case kLocalF64:
923 return kAstF64; 637 return kAstF64;
924 case kLocalS128: 638 case kLocalS128:
925 return kAstS128; 639 return kAstS128;
926 default: 640 default:
927 error(pc_ - 1, "invalid local type"); 641 error(pc_ - 1, "invalid local type");
928 return kAstStmt; 642 return kAstStmt;
929 } 643 }
930 } 644 }
931 645
932 // Parses a type entry, which is currently limited to functions only. 646 // Parses a type entry, which is currently limited to functions only.
933 FunctionSig* consume_sig() { 647 FunctionSig* consume_sig() {
934 if (!expect_u8("type form", kWasmFunctionTypeForm)) return nullptr; 648 const byte* pos = pc_;
649 byte form = consume_u8("type form");
650 if (form != kWasmFunctionTypeForm) {
651 error(pos, pos, "expected function type form (0x%02x), got: 0x%02x",
652 kWasmFunctionTypeForm, form);
653 return nullptr;
654 }
935 // parse parameter types 655 // parse parameter types
936 uint32_t param_count = consume_u32v("param count"); 656 uint32_t param_count = consume_u32v("param count");
937 std::vector<LocalType> params; 657 std::vector<LocalType> params;
938 for (uint32_t i = 0; ok() && i < param_count; ++i) { 658 for (uint32_t i = 0; i < param_count; ++i) {
939 LocalType param = consume_value_type(); 659 LocalType param = consume_local_type();
660 if (param == kAstStmt) error(pc_ - 1, "invalid void parameter type");
940 params.push_back(param); 661 params.push_back(param);
941 } 662 }
942 663
943 // parse return types 664 // parse return types
944 const byte* pt = pc_; 665 const byte* pt = pc_;
945 uint32_t return_count = consume_u32v("return count"); 666 uint32_t return_count = consume_u32v("return count");
946 if (return_count > kMaxReturnCount) { 667 if (return_count > kMaxReturnCount) {
947 error(pt, pt, "return count of %u exceeds maximum of %u", return_count, 668 error(pt, pt, "return count of %u exceeds maximum of %u", return_count,
948 kMaxReturnCount); 669 kMaxReturnCount);
949 return nullptr; 670 return nullptr;
950 } 671 }
951 std::vector<LocalType> returns; 672 std::vector<LocalType> returns;
952 for (uint32_t i = 0; ok() && i < return_count; ++i) { 673 for (uint32_t i = 0; i < return_count; ++i) {
953 LocalType ret = consume_value_type(); 674 LocalType ret = consume_local_type();
675 if (ret == kAstStmt) error(pc_ - 1, "invalid void return type");
954 returns.push_back(ret); 676 returns.push_back(ret);
955 } 677 }
956 678
957 if (failed()) {
958 // Decoding failed, return void -> void
959 return new (module_zone) FunctionSig(0, 0, nullptr);
960 }
961
962 // FunctionSig stores the return types first. 679 // FunctionSig stores the return types first.
963 LocalType* buffer = 680 LocalType* buffer =
964 module_zone->NewArray<LocalType>(param_count + return_count); 681 module_zone->NewArray<LocalType>(param_count + return_count);
965 uint32_t b = 0; 682 uint32_t b = 0;
966 for (uint32_t i = 0; i < return_count; ++i) buffer[b++] = returns[i]; 683 for (uint32_t i = 0; i < return_count; ++i) buffer[b++] = returns[i];
967 for (uint32_t i = 0; i < param_count; ++i) buffer[b++] = params[i]; 684 for (uint32_t i = 0; i < param_count; ++i) buffer[b++] = params[i];
968 685
969 return new (module_zone) FunctionSig(return_count, param_count, buffer); 686 return new (module_zone) FunctionSig(return_count, param_count, buffer);
970 } 687 }
971 }; 688 };
(...skipping 18 matching lines...) Expand all
990 error_code = kError; 707 error_code = kError;
991 size_t len = strlen(msg) + 1; 708 size_t len = strlen(msg) + 1;
992 char* result = new char[len]; 709 char* result = new char[len];
993 strncpy(result, msg, len); 710 strncpy(result, msg, len);
994 result[len - 1] = 0; 711 result[len - 1] = 0;
995 error_msg.reset(result); 712 error_msg.reset(result);
996 } 713 }
997 }; 714 };
998 715
999 Vector<const byte> FindSection(const byte* module_start, const byte* module_end, 716 Vector<const byte> FindSection(const byte* module_start, const byte* module_end,
1000 WasmSectionCode code) { 717 WasmSection::Code code) {
1001 Decoder decoder(module_start, module_end); 718 Decoder decoder(module_start, module_end);
1002 719
1003 uint32_t magic_word = decoder.consume_u32("wasm magic"); 720 uint32_t magic_word = decoder.consume_u32("wasm magic");
1004 if (magic_word != kWasmMagic) decoder.error("wrong magic word"); 721 if (magic_word != kWasmMagic) decoder.error("wrong magic word");
1005 722
1006 uint32_t magic_version = decoder.consume_u32("wasm version"); 723 uint32_t magic_version = decoder.consume_u32("wasm version");
1007 if (magic_version != kWasmVersion) decoder.error("wrong wasm version"); 724 if (magic_version != kWasmVersion) decoder.error("wrong wasm version");
1008 725
1009 WasmSectionIterator section_iter(decoder); 726 while (decoder.more() && decoder.ok()) {
1010 while (section_iter.more()) { 727 // Read the section name.
1011 if (section_iter.section_code() == code) { 728 uint32_t string_length = decoder.consume_u32v("section name length");
1012 return Vector<const uint8_t>(section_iter.section_start(), 729 const byte* section_name_start = decoder.pc();
1013 section_iter.section_length()); 730 decoder.consume_bytes(string_length);
731 if (decoder.failed()) break;
732
733 WasmSection::Code section =
734 WasmSection::lookup(section_name_start, string_length);
735
736 // Read and check the section size.
737 uint32_t section_length = decoder.consume_u32v("section length");
738
739 const byte* section_start = decoder.pc();
740 decoder.consume_bytes(section_length);
741 if (section == code && decoder.ok()) {
742 return Vector<const uint8_t>(section_start, section_length);
1014 } 743 }
1015 decoder.consume_bytes(section_iter.section_length(), "section payload");
1016 section_iter.advance();
1017 } 744 }
1018 745
1019 return Vector<const uint8_t>(); 746 return Vector<const uint8_t>();
1020 } 747 }
1021 748
1022 } // namespace 749 } // namespace
1023 750
1024 ModuleResult DecodeWasmModule(Isolate* isolate, Zone* zone, 751 ModuleResult DecodeWasmModule(Isolate* isolate, Zone* zone,
1025 const byte* module_start, const byte* module_end, 752 const byte* module_start, const byte* module_end,
1026 bool verify_functions, ModuleOrigin origin) { 753 bool verify_functions, ModuleOrigin origin) {
(...skipping 14 matching lines...) Expand all
1041 static_cast<int>(zone->allocation_size() - decode_memory_start)); 768 static_cast<int>(zone->allocation_size() - decode_memory_start));
1042 return result; 769 return result;
1043 } 770 }
1044 771
1045 FunctionSig* DecodeWasmSignatureForTesting(Zone* zone, const byte* start, 772 FunctionSig* DecodeWasmSignatureForTesting(Zone* zone, const byte* start,
1046 const byte* end) { 773 const byte* end) {
1047 ModuleDecoder decoder(zone, start, end, kWasmOrigin); 774 ModuleDecoder decoder(zone, start, end, kWasmOrigin);
1048 return decoder.DecodeFunctionSignature(start); 775 return decoder.DecodeFunctionSignature(start);
1049 } 776 }
1050 777
1051 WasmInitExpr DecodeWasmInitExprForTesting(const byte* start, const byte* end) {
1052 AccountingAllocator allocator;
1053 Zone zone(&allocator);
1054 ModuleDecoder decoder(&zone, start, end, kWasmOrigin);
1055 return decoder.DecodeInitExpr(start);
1056 }
1057
1058 FunctionResult DecodeWasmFunction(Isolate* isolate, Zone* zone, 778 FunctionResult DecodeWasmFunction(Isolate* isolate, Zone* zone,
1059 ModuleEnv* module_env, 779 ModuleEnv* module_env,
1060 const byte* function_start, 780 const byte* function_start,
1061 const byte* function_end) { 781 const byte* function_end) {
1062 HistogramTimerScope wasm_decode_function_time_scope( 782 HistogramTimerScope wasm_decode_function_time_scope(
1063 isolate->counters()->wasm_decode_function_time()); 783 isolate->counters()->wasm_decode_function_time());
1064 size_t size = function_end - function_start; 784 size_t size = function_end - function_start;
1065 if (function_start > function_end) return FunctionError("start > end"); 785 if (function_start > function_end) return FunctionError("start > end");
1066 if (size > kMaxFunctionSize) 786 if (size > kMaxFunctionSize)
1067 return FunctionError("size > maximum function size"); 787 return FunctionError("size > maximum function size");
1068 isolate->counters()->wasm_function_size_bytes()->AddSample( 788 isolate->counters()->wasm_function_size_bytes()->AddSample(
1069 static_cast<int>(size)); 789 static_cast<int>(size));
1070 WasmFunction* function = new WasmFunction(); 790 WasmFunction* function = new WasmFunction();
1071 ModuleDecoder decoder(zone, function_start, function_end, kWasmOrigin); 791 ModuleDecoder decoder(zone, function_start, function_end, kWasmOrigin);
1072 return decoder.DecodeSingleFunction(module_env, function); 792 return decoder.DecodeSingleFunction(module_env, function);
1073 } 793 }
1074 794
1075 FunctionOffsetsResult DecodeWasmFunctionOffsets( 795 FunctionOffsetsResult DecodeWasmFunctionOffsets(const byte* module_start,
1076 const byte* module_start, const byte* module_end, 796 const byte* module_end) {
1077 uint32_t num_imported_functions) {
1078 // Find and decode the code section.
1079 Vector<const byte> code_section = 797 Vector<const byte> code_section =
1080 FindSection(module_start, module_end, kCodeSectionCode); 798 FindSection(module_start, module_end, WasmSection::Code::FunctionBodies);
1081 Decoder decoder(code_section.start(), code_section.end()); 799 Decoder decoder(code_section.start(), code_section.end());
1082 FunctionOffsets table; 800 if (!code_section.start()) decoder.error("no code section");
1083 if (!code_section.start()) {
1084 decoder.error("no code section");
1085 return decoder.toResult(std::move(table));
1086 }
1087
1088 // Reserve entries for the imported functions.
1089 table.reserve(num_imported_functions);
1090 for (uint32_t i = 0; i < num_imported_functions; i++) {
1091 table.push_back(std::make_pair(0, 0));
1092 }
1093 801
1094 uint32_t functions_count = decoder.consume_u32v("functions count"); 802 uint32_t functions_count = decoder.consume_u32v("functions count");
803 FunctionOffsets table;
1095 // Take care of invalid input here. 804 // Take care of invalid input here.
1096 if (functions_count < static_cast<unsigned>(code_section.length()) / 2) 805 if (functions_count < static_cast<unsigned>(code_section.length()) / 2)
1097 table.reserve(functions_count); 806 table.reserve(functions_count);
1098 int section_offset = static_cast<int>(code_section.start() - module_start); 807 int section_offset = static_cast<int>(code_section.start() - module_start);
1099 DCHECK_LE(0, section_offset); 808 DCHECK_LE(0, section_offset);
1100 for (uint32_t i = 0; i < functions_count && decoder.ok(); ++i) { 809 for (uint32_t i = 0; i < functions_count && decoder.ok(); ++i) {
1101 uint32_t size = decoder.consume_u32v("body size"); 810 uint32_t size = decoder.consume_u32v("body size");
1102 int offset = static_cast<int>(section_offset + decoder.pc_offset()); 811 int offset = static_cast<int>(section_offset + decoder.pc_offset());
1103 table.push_back(std::make_pair(offset, static_cast<int>(size))); 812 table.push_back(std::make_pair(offset, static_cast<int>(size)));
1104 DCHECK(table.back().first >= 0 && table.back().second >= 0); 813 DCHECK(table.back().first >= 0 && table.back().second >= 0);
1105 decoder.consume_bytes(size); 814 decoder.consume_bytes(size);
1106 } 815 }
1107 if (decoder.more()) decoder.error("unexpected additional bytes"); 816 if (decoder.more()) decoder.error("unexpected additional bytes");
1108 817
1109 return decoder.toResult(std::move(table)); 818 return decoder.toResult(std::move(table));
1110 } 819 }
1111 820
1112 } // namespace wasm 821 } // namespace wasm
1113 } // namespace internal 822 } // namespace internal
1114 } // namespace v8 823 } // namespace v8
OLDNEW
« no previous file with comments | « src/wasm/module-decoder.h ('k') | src/wasm/wasm-debug.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698