| OLD | NEW |
| 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" |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 module->min_mem_pages = consume_u32v(&length, "min memory"); | 150 module->min_mem_pages = consume_u32v(&length, "min memory"); |
| 151 module->max_mem_pages = consume_u32v(&length, "max memory"); | 151 module->max_mem_pages = consume_u32v(&length, "max memory"); |
| 152 module->mem_export = consume_u8("export memory") != 0; | 152 module->mem_export = consume_u8("export memory") != 0; |
| 153 break; | 153 break; |
| 154 } | 154 } |
| 155 case WasmSection::Code::Signatures: { | 155 case WasmSection::Code::Signatures: { |
| 156 int length; | 156 int length; |
| 157 uint32_t signatures_count = consume_u32v(&length, "signatures count"); | 157 uint32_t signatures_count = consume_u32v(&length, "signatures count"); |
| 158 module->signatures.reserve(SafeReserve(signatures_count)); | 158 module->signatures.reserve(SafeReserve(signatures_count)); |
| 159 // Decode signatures. | 159 // Decode signatures. |
| 160 for (uint32_t i = 0; i < signatures_count; i++) { | 160 for (uint32_t i = 0; i < signatures_count; ++i) { |
| 161 if (failed()) break; | 161 if (failed()) break; |
| 162 TRACE("DecodeSignature[%d] module+%d\n", i, | 162 TRACE("DecodeSignature[%d] module+%d\n", i, |
| 163 static_cast<int>(pc_ - start_)); | 163 static_cast<int>(pc_ - start_)); |
| 164 FunctionSig* s = consume_sig(); | 164 FunctionSig* s = consume_sig(); |
| 165 module->signatures.push_back(s); | 165 module->signatures.push_back(s); |
| 166 } | 166 } |
| 167 break; | 167 break; |
| 168 } | 168 } |
| 169 case WasmSection::Code::FunctionSignatures: { | 169 case WasmSection::Code::FunctionSignatures: { |
| 170 int length; | 170 int length; |
| 171 uint32_t functions_count = consume_u32v(&length, "functions count"); | 171 uint32_t functions_count = consume_u32v(&length, "functions count"); |
| 172 module->functions.reserve(SafeReserve(functions_count)); | 172 module->functions.reserve(SafeReserve(functions_count)); |
| 173 for (uint32_t i = 0; i < functions_count; i++) { | 173 for (uint32_t i = 0; i < functions_count; ++i) { |
| 174 module->functions.push_back({nullptr, // sig | 174 module->functions.push_back({nullptr, // sig |
| 175 i, // func_index | 175 i, // func_index |
| 176 0, // sig_index | 176 0, // sig_index |
| 177 0, // name_offset | 177 0, // name_offset |
| 178 0, // name_length | 178 0, // name_length |
| 179 0, // code_start_offset | 179 0, // code_start_offset |
| 180 0}); // code_end_offset | 180 0}); // code_end_offset |
| 181 WasmFunction* function = &module->functions.back(); | 181 WasmFunction* function = &module->functions.back(); |
| 182 function->sig_index = consume_sig_index(module, &function->sig); | 182 function->sig_index = consume_sig_index(module, &function->sig); |
| 183 } | 183 } |
| 184 break; | 184 break; |
| 185 } | 185 } |
| 186 case WasmSection::Code::FunctionBodies: { | 186 case WasmSection::Code::FunctionBodies: { |
| 187 int length; | 187 int length; |
| 188 const byte* pos = pc_; | 188 const byte* pos = pc_; |
| 189 uint32_t functions_count = consume_u32v(&length, "functions count"); | 189 uint32_t functions_count = consume_u32v(&length, "functions count"); |
| 190 if (functions_count != module->functions.size()) { | 190 if (functions_count != module->functions.size()) { |
| 191 error(pos, pos, "function body count %u mismatch (%u expected)", | 191 error(pos, pos, "function body count %u mismatch (%u expected)", |
| 192 functions_count, | 192 functions_count, |
| 193 static_cast<uint32_t>(module->functions.size())); | 193 static_cast<uint32_t>(module->functions.size())); |
| 194 break; | 194 break; |
| 195 } | 195 } |
| 196 for (uint32_t i = 0; i < functions_count; i++) { | 196 for (uint32_t i = 0; i < functions_count; ++i) { |
| 197 WasmFunction* function = &module->functions[i]; | 197 WasmFunction* function = &module->functions[i]; |
| 198 int length; | 198 int length; |
| 199 uint32_t size = consume_u32v(&length, "body size"); | 199 uint32_t size = consume_u32v(&length, "body size"); |
| 200 function->code_start_offset = pc_offset(); | 200 function->code_start_offset = pc_offset(); |
| 201 function->code_end_offset = pc_offset() + size; | 201 function->code_end_offset = pc_offset() + size; |
| 202 | 202 |
| 203 TRACE(" +%d %-20s: (%d bytes)\n", pc_offset(), "function body", | 203 TRACE(" +%d %-20s: (%d bytes)\n", pc_offset(), "function body", |
| 204 size); | 204 size); |
| 205 pc_ += size; | 205 pc_ += size; |
| 206 if (pc_ > limit_) { | 206 if (pc_ > limit_) { |
| 207 error(pc_, "function body extends beyond end of file"); | 207 error(pc_, "function body extends beyond end of file"); |
| 208 } | 208 } |
| 209 } | 209 } |
| 210 break; | 210 break; |
| 211 } | 211 } |
| 212 case WasmSection::Code::Names: { | 212 case WasmSection::Code::Names: { |
| 213 int length; | 213 int length; |
| 214 const byte* pos = pc_; | 214 const byte* pos = pc_; |
| 215 uint32_t functions_count = consume_u32v(&length, "functions count"); | 215 uint32_t functions_count = consume_u32v(&length, "functions count"); |
| 216 if (functions_count != module->functions.size()) { | 216 if (functions_count != module->functions.size()) { |
| 217 error(pos, pos, "function name count %u mismatch (%u expected)", | 217 error(pos, pos, "function name count %u mismatch (%u expected)", |
| 218 functions_count, | 218 functions_count, |
| 219 static_cast<uint32_t>(module->functions.size())); | 219 static_cast<uint32_t>(module->functions.size())); |
| 220 break; | 220 break; |
| 221 } | 221 } |
| 222 | 222 |
| 223 for (uint32_t i = 0; i < functions_count; i++) { | 223 for (uint32_t i = 0; i < functions_count; ++i) { |
| 224 WasmFunction* function = &module->functions[i]; | 224 WasmFunction* function = &module->functions[i]; |
| 225 function->name_offset = | 225 function->name_offset = |
| 226 consume_string(&function->name_length, false); | 226 consume_string(&function->name_length, false); |
| 227 | 227 |
| 228 uint32_t local_names_count = | 228 uint32_t local_names_count = |
| 229 consume_u32v(&length, "local names count"); | 229 consume_u32v(&length, "local names count"); |
| 230 for (uint32_t j = 0; j < local_names_count; j++) { | 230 for (uint32_t j = 0; j < local_names_count; j++) { |
| 231 uint32_t unused = 0; | 231 uint32_t unused = 0; |
| 232 uint32_t offset = consume_string(&unused, false); | 232 uint32_t offset = consume_string(&unused, false); |
| 233 USE(unused); | 233 USE(unused); |
| 234 USE(offset); | 234 USE(offset); |
| 235 } | 235 } |
| 236 } | 236 } |
| 237 break; | 237 break; |
| 238 } | 238 } |
| 239 case WasmSection::Code::Globals: { | 239 case WasmSection::Code::Globals: { |
| 240 int length; | 240 int length; |
| 241 uint32_t globals_count = consume_u32v(&length, "globals count"); | 241 uint32_t globals_count = consume_u32v(&length, "globals count"); |
| 242 module->globals.reserve(SafeReserve(globals_count)); | 242 module->globals.reserve(SafeReserve(globals_count)); |
| 243 // Decode globals. | 243 // Decode globals. |
| 244 for (uint32_t i = 0; i < globals_count; i++) { | 244 for (uint32_t i = 0; i < globals_count; ++i) { |
| 245 if (failed()) break; | 245 if (failed()) break; |
| 246 TRACE("DecodeGlobal[%d] module+%d\n", i, | 246 TRACE("DecodeGlobal[%d] module+%d\n", i, |
| 247 static_cast<int>(pc_ - start_)); | 247 static_cast<int>(pc_ - start_)); |
| 248 module->globals.push_back({0, 0, MachineType::Int32(), 0, false}); | 248 module->globals.push_back({0, 0, MachineType::Int32(), 0, false}); |
| 249 WasmGlobal* global = &module->globals.back(); | 249 WasmGlobal* global = &module->globals.back(); |
| 250 DecodeGlobalInModule(global); | 250 DecodeGlobalInModule(global); |
| 251 } | 251 } |
| 252 break; | 252 break; |
| 253 } | 253 } |
| 254 case WasmSection::Code::DataSegments: { | 254 case WasmSection::Code::DataSegments: { |
| 255 int length; | 255 int length; |
| 256 uint32_t data_segments_count = | 256 uint32_t data_segments_count = |
| 257 consume_u32v(&length, "data segments count"); | 257 consume_u32v(&length, "data segments count"); |
| 258 module->data_segments.reserve(SafeReserve(data_segments_count)); | 258 module->data_segments.reserve(SafeReserve(data_segments_count)); |
| 259 // Decode data segments. | 259 // Decode data segments. |
| 260 for (uint32_t i = 0; i < data_segments_count; i++) { | 260 for (uint32_t i = 0; i < data_segments_count; ++i) { |
| 261 if (failed()) break; | 261 if (failed()) break; |
| 262 TRACE("DecodeDataSegment[%d] module+%d\n", i, | 262 TRACE("DecodeDataSegment[%d] module+%d\n", i, |
| 263 static_cast<int>(pc_ - start_)); | 263 static_cast<int>(pc_ - start_)); |
| 264 module->data_segments.push_back({0, // dest_addr | 264 module->data_segments.push_back({0, // dest_addr |
| 265 0, // source_offset | 265 0, // source_offset |
| 266 0, // source_size | 266 0, // source_size |
| 267 false}); // init | 267 false}); // init |
| 268 WasmDataSegment* segment = &module->data_segments.back(); | 268 WasmDataSegment* segment = &module->data_segments.back(); |
| 269 DecodeDataSegmentInModule(module, segment); | 269 DecodeDataSegmentInModule(module, segment); |
| 270 } | 270 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 285 break; | 285 break; |
| 286 } | 286 } |
| 287 case WasmSection::Code::FunctionTable: { | 287 case WasmSection::Code::FunctionTable: { |
| 288 // An indirect function table requires functions first. | 288 // An indirect function table requires functions first. |
| 289 CheckForFunctions(module, section); | 289 CheckForFunctions(module, section); |
| 290 int length; | 290 int length; |
| 291 uint32_t function_table_count = | 291 uint32_t function_table_count = |
| 292 consume_u32v(&length, "function table count"); | 292 consume_u32v(&length, "function table count"); |
| 293 module->function_table.reserve(SafeReserve(function_table_count)); | 293 module->function_table.reserve(SafeReserve(function_table_count)); |
| 294 // Decode function table. | 294 // Decode function table. |
| 295 for (uint32_t i = 0; i < function_table_count; i++) { | 295 for (uint32_t i = 0; i < function_table_count; ++i) { |
| 296 if (failed()) break; | 296 if (failed()) break; |
| 297 TRACE("DecodeFunctionTable[%d] module+%d\n", i, | 297 TRACE("DecodeFunctionTable[%d] module+%d\n", i, |
| 298 static_cast<int>(pc_ - start_)); | 298 static_cast<int>(pc_ - start_)); |
| 299 uint16_t index = consume_u32v(&length); | 299 uint16_t index = consume_u32v(&length); |
| 300 if (index >= module->functions.size()) { | 300 if (index >= module->functions.size()) { |
| 301 error(pc_ - 2, "invalid function index"); | 301 error(pc_ - 2, "invalid function index"); |
| 302 break; | 302 break; |
| 303 } | 303 } |
| 304 module->function_table.push_back(index); | 304 module->function_table.push_back(index); |
| 305 } | 305 } |
| (...skipping 18 matching lines...) Expand all Loading... |
| 324 break; | 324 break; |
| 325 } | 325 } |
| 326 break; | 326 break; |
| 327 } | 327 } |
| 328 case WasmSection::Code::ImportTable: { | 328 case WasmSection::Code::ImportTable: { |
| 329 int length; | 329 int length; |
| 330 uint32_t import_table_count = | 330 uint32_t import_table_count = |
| 331 consume_u32v(&length, "import table count"); | 331 consume_u32v(&length, "import table count"); |
| 332 module->import_table.reserve(SafeReserve(import_table_count)); | 332 module->import_table.reserve(SafeReserve(import_table_count)); |
| 333 // Decode import table. | 333 // Decode import table. |
| 334 for (uint32_t i = 0; i < import_table_count; i++) { | 334 for (uint32_t i = 0; i < import_table_count; ++i) { |
| 335 if (failed()) break; | 335 if (failed()) break; |
| 336 TRACE("DecodeImportTable[%d] module+%d\n", i, | 336 TRACE("DecodeImportTable[%d] module+%d\n", i, |
| 337 static_cast<int>(pc_ - start_)); | 337 static_cast<int>(pc_ - start_)); |
| 338 | 338 |
| 339 module->import_table.push_back({nullptr, // sig | 339 module->import_table.push_back({nullptr, // sig |
| 340 0, // sig_index | 340 0, // sig_index |
| 341 0, // module_name_offset | 341 0, // module_name_offset |
| 342 0, // module_name_length | 342 0, // module_name_length |
| 343 0, // function_name_offset | 343 0, // function_name_offset |
| 344 0}); // function_name_length | 344 0}); // function_name_length |
| (...skipping 12 matching lines...) Expand all Loading... |
| 357 break; | 357 break; |
| 358 } | 358 } |
| 359 case WasmSection::Code::ExportTable: { | 359 case WasmSection::Code::ExportTable: { |
| 360 // Declares an export table. | 360 // Declares an export table. |
| 361 CheckForFunctions(module, section); | 361 CheckForFunctions(module, section); |
| 362 int length; | 362 int length; |
| 363 uint32_t export_table_count = | 363 uint32_t export_table_count = |
| 364 consume_u32v(&length, "export table count"); | 364 consume_u32v(&length, "export table count"); |
| 365 module->export_table.reserve(SafeReserve(export_table_count)); | 365 module->export_table.reserve(SafeReserve(export_table_count)); |
| 366 // Decode export table. | 366 // Decode export table. |
| 367 for (uint32_t i = 0; i < export_table_count; i++) { | 367 for (uint32_t i = 0; i < export_table_count; ++i) { |
| 368 if (failed()) break; | 368 if (failed()) break; |
| 369 TRACE("DecodeExportTable[%d] module+%d\n", i, | 369 TRACE("DecodeExportTable[%d] module+%d\n", i, |
| 370 static_cast<int>(pc_ - start_)); | 370 static_cast<int>(pc_ - start_)); |
| 371 | 371 |
| 372 module->export_table.push_back({0, // func_index | 372 module->export_table.push_back({0, // func_index |
| 373 0, // name_offset | 373 0, // name_offset |
| 374 0}); // name_length | 374 0}); // name_length |
| 375 WasmExport* exp = &module->export_table.back(); | 375 WasmExport* exp = &module->export_table.back(); |
| 376 | 376 |
| 377 WasmFunction* func; | 377 WasmFunction* func; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 402 it->name_length, pc, last->func_index, it->func_index); | 402 it->name_length, pc, last->func_index, it->func_index); |
| 403 break; | 403 break; |
| 404 } | 404 } |
| 405 } | 405 } |
| 406 } | 406 } |
| 407 break; | 407 break; |
| 408 } | 408 } |
| 409 case WasmSection::Code::Max: | 409 case WasmSection::Code::Max: |
| 410 // Skip unknown sections. | 410 // Skip unknown sections. |
| 411 TRACE("Unknown section: '"); | 411 TRACE("Unknown section: '"); |
| 412 for (uint32_t i = 0; i != string_length; i++) { | 412 for (uint32_t i = 0; i != string_length; ++i) { |
| 413 TRACE("%c", *(section_name_start + i)); | 413 TRACE("%c", *(section_name_start + i)); |
| 414 } | 414 } |
| 415 TRACE("'\n"); | 415 TRACE("'\n"); |
| 416 consume_bytes(section_length); | 416 consume_bytes(section_length); |
| 417 break; | 417 break; |
| 418 } | 418 } |
| 419 | 419 |
| 420 if (pc_ != expected_section_end) { | 420 if (pc_ != expected_section_end) { |
| 421 const char* diff = pc_ < expected_section_end ? "shorter" : "longer"; | 421 const char* diff = pc_ < expected_section_end ? "shorter" : "longer"; |
| 422 size_t expected_length = static_cast<size_t>(section_length); | 422 size_t expected_length = static_cast<size_t>(section_length); |
| (...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 700 byte form = consume_u8("type form"); | 700 byte form = consume_u8("type form"); |
| 701 if (form != kWasmFunctionTypeForm) { | 701 if (form != kWasmFunctionTypeForm) { |
| 702 error(pos, pos, "expected function type form (0x%02x), got: 0x%02x", | 702 error(pos, pos, "expected function type form (0x%02x), got: 0x%02x", |
| 703 kWasmFunctionTypeForm, form); | 703 kWasmFunctionTypeForm, form); |
| 704 return nullptr; | 704 return nullptr; |
| 705 } | 705 } |
| 706 int length; | 706 int length; |
| 707 // parse parameter types | 707 // parse parameter types |
| 708 uint32_t param_count = consume_u32v(&length, "param count"); | 708 uint32_t param_count = consume_u32v(&length, "param count"); |
| 709 std::vector<LocalType> params; | 709 std::vector<LocalType> params; |
| 710 for (uint32_t i = 0; i < param_count; i++) { | 710 for (uint32_t i = 0; i < param_count; ++i) { |
| 711 LocalType param = consume_local_type(); | 711 LocalType param = consume_local_type(); |
| 712 if (param == kAstStmt) error(pc_ - 1, "invalid void parameter type"); | 712 if (param == kAstStmt) error(pc_ - 1, "invalid void parameter type"); |
| 713 params.push_back(param); | 713 params.push_back(param); |
| 714 } | 714 } |
| 715 | 715 |
| 716 // parse return types | 716 // parse return types |
| 717 const byte* pt = pc_; | 717 const byte* pt = pc_; |
| 718 uint32_t return_count = consume_u32v(&length, "return count"); | 718 uint32_t return_count = consume_u32v(&length, "return count"); |
| 719 if (return_count > kMaxReturnCount) { | 719 if (return_count > kMaxReturnCount) { |
| 720 error(pt, pt, "return count of %u exceeds maximum of %u", return_count, | 720 error(pt, pt, "return count of %u exceeds maximum of %u", return_count, |
| 721 kMaxReturnCount); | 721 kMaxReturnCount); |
| 722 return nullptr; | 722 return nullptr; |
| 723 } | 723 } |
| 724 std::vector<LocalType> returns; | 724 std::vector<LocalType> returns; |
| 725 for (uint32_t i = 0; i < return_count; i++) { | 725 for (uint32_t i = 0; i < return_count; ++i) { |
| 726 LocalType ret = consume_local_type(); | 726 LocalType ret = consume_local_type(); |
| 727 if (ret == kAstStmt) error(pc_ - 1, "invalid void return type"); | 727 if (ret == kAstStmt) error(pc_ - 1, "invalid void return type"); |
| 728 returns.push_back(ret); | 728 returns.push_back(ret); |
| 729 } | 729 } |
| 730 | 730 |
| 731 // FunctionSig stores the return types first. | 731 // FunctionSig stores the return types first. |
| 732 LocalType* buffer = | 732 LocalType* buffer = |
| 733 module_zone->NewArray<LocalType>(param_count + return_count); | 733 module_zone->NewArray<LocalType>(param_count + return_count); |
| 734 uint32_t b = 0; | 734 uint32_t b = 0; |
| 735 for (uint32_t i = 0; i < return_count; i++) buffer[b++] = returns[i]; | 735 for (uint32_t i = 0; i < return_count; ++i) buffer[b++] = returns[i]; |
| 736 for (uint32_t i = 0; i < param_count; i++) buffer[b++] = params[i]; | 736 for (uint32_t i = 0; i < param_count; ++i) buffer[b++] = params[i]; |
| 737 | 737 |
| 738 return new (module_zone) FunctionSig(return_count, param_count, buffer); | 738 return new (module_zone) FunctionSig(return_count, param_count, buffer); |
| 739 } | 739 } |
| 740 }; | 740 }; |
| 741 | 741 |
| 742 // Helpers for nice error messages. | 742 // Helpers for nice error messages. |
| 743 class ModuleError : public ModuleResult { | 743 class ModuleError : public ModuleResult { |
| 744 public: | 744 public: |
| 745 explicit ModuleError(const char* msg) { | 745 explicit ModuleError(const char* msg) { |
| 746 error_code = kError; | 746 error_code = kError; |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 856 if (!code_section.start()) decoder.error("no code section"); | 856 if (!code_section.start()) decoder.error("no code section"); |
| 857 | 857 |
| 858 int length; | 858 int length; |
| 859 uint32_t functions_count = decoder.consume_u32v(&length, "functions count"); | 859 uint32_t functions_count = decoder.consume_u32v(&length, "functions count"); |
| 860 FunctionOffsets table; | 860 FunctionOffsets table; |
| 861 // Take care of invalid input here. | 861 // Take care of invalid input here. |
| 862 if (functions_count < static_cast<unsigned>(code_section.length()) / 2) | 862 if (functions_count < static_cast<unsigned>(code_section.length()) / 2) |
| 863 table.reserve(functions_count); | 863 table.reserve(functions_count); |
| 864 int section_offset = static_cast<int>(code_section.start() - module_start); | 864 int section_offset = static_cast<int>(code_section.start() - module_start); |
| 865 DCHECK_LE(0, section_offset); | 865 DCHECK_LE(0, section_offset); |
| 866 for (uint32_t i = 0; i < functions_count && decoder.ok(); i++) { | 866 for (uint32_t i = 0; i < functions_count && decoder.ok(); ++i) { |
| 867 uint32_t size = decoder.consume_u32v(&length, "body size"); | 867 uint32_t size = decoder.consume_u32v(&length, "body size"); |
| 868 int offset = static_cast<int>(section_offset + decoder.pc_offset()); | 868 int offset = static_cast<int>(section_offset + decoder.pc_offset()); |
| 869 table.push_back(std::make_pair(offset, static_cast<int>(size))); | 869 table.push_back(std::make_pair(offset, static_cast<int>(size))); |
| 870 DCHECK(table.back().first >= 0 && table.back().second >= 0); | 870 DCHECK(table.back().first >= 0 && table.back().second >= 0); |
| 871 decoder.consume_bytes(size); | 871 decoder.consume_bytes(size); |
| 872 } | 872 } |
| 873 if (decoder.more()) decoder.error("unexpected additional bytes"); | 873 if (decoder.more()) decoder.error("unexpected additional bytes"); |
| 874 | 874 |
| 875 return decoder.toResult(std::move(table)); | 875 return decoder.toResult(std::move(table)); |
| 876 } | 876 } |
| 877 | 877 |
| 878 } // namespace wasm | 878 } // namespace wasm |
| 879 } // namespace internal | 879 } // namespace internal |
| 880 } // namespace v8 | 880 } // namespace v8 |
| OLD | NEW |