| 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 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 144 case WasmSection::Code::Memory: { | 144 case WasmSection::Code::Memory: { |
| 145 module->min_mem_pages = consume_u32v("min memory"); | 145 module->min_mem_pages = consume_u32v("min memory"); |
| 146 module->max_mem_pages = consume_u32v("max memory"); | 146 module->max_mem_pages = consume_u32v("max memory"); |
| 147 module->mem_export = consume_u8("export memory") != 0; | 147 module->mem_export = consume_u8("export memory") != 0; |
| 148 break; | 148 break; |
| 149 } | 149 } |
| 150 case WasmSection::Code::Signatures: { | 150 case WasmSection::Code::Signatures: { |
| 151 uint32_t signatures_count = consume_u32v("signatures count"); | 151 uint32_t signatures_count = consume_u32v("signatures count"); |
| 152 module->signatures.reserve(SafeReserve(signatures_count)); | 152 module->signatures.reserve(SafeReserve(signatures_count)); |
| 153 // Decode signatures. | 153 // Decode signatures. |
| 154 for (uint32_t i = 0; i < signatures_count; ++i) { | 154 for (uint32_t i = 0; ok() && i < signatures_count; ++i) { |
| 155 if (failed()) break; | |
| 156 TRACE("DecodeSignature[%d] module+%d\n", i, | 155 TRACE("DecodeSignature[%d] module+%d\n", i, |
| 157 static_cast<int>(pc_ - start_)); | 156 static_cast<int>(pc_ - start_)); |
| 158 FunctionSig* s = consume_sig(); | 157 FunctionSig* s = consume_sig(); |
| 159 module->signatures.push_back(s); | 158 module->signatures.push_back(s); |
| 160 } | 159 } |
| 161 break; | 160 break; |
| 162 } | 161 } |
| 163 case WasmSection::Code::FunctionSignatures: { | 162 case WasmSection::Code::FunctionSignatures: { |
| 164 uint32_t functions_count = consume_u32v("functions count"); | 163 uint32_t functions_count = consume_u32v("functions count"); |
| 165 module->functions.reserve(SafeReserve(functions_count)); | 164 module->functions.reserve(SafeReserve(functions_count)); |
| 166 for (uint32_t i = 0; i < functions_count; ++i) { | 165 for (uint32_t i = 0; ok() && i < functions_count; ++i) { |
| 167 if (failed()) break; | |
| 168 module->functions.push_back({nullptr, // sig | 166 module->functions.push_back({nullptr, // sig |
| 169 i, // func_index | 167 i, // func_index |
| 170 0, // sig_index | 168 0, // sig_index |
| 171 0, // name_offset | 169 0, // name_offset |
| 172 0, // name_length | 170 0, // name_length |
| 173 0, // code_start_offset | 171 0, // code_start_offset |
| 174 0}); // code_end_offset | 172 0}); // code_end_offset |
| 175 WasmFunction* function = &module->functions.back(); | 173 WasmFunction* function = &module->functions.back(); |
| 176 function->sig_index = consume_sig_index(module, &function->sig); | 174 function->sig_index = consume_sig_index(module, &function->sig); |
| 177 } | 175 } |
| 178 break; | 176 break; |
| 179 } | 177 } |
| 180 case WasmSection::Code::FunctionBodies: { | 178 case WasmSection::Code::FunctionBodies: { |
| 181 const byte* pos = pc_; | 179 const byte* pos = pc_; |
| 182 uint32_t functions_count = consume_u32v("functions count"); | 180 uint32_t functions_count = consume_u32v("functions count"); |
| 183 if (functions_count != module->functions.size()) { | 181 if (functions_count != module->functions.size()) { |
| 184 error(pos, pos, "function body count %u mismatch (%u expected)", | 182 error(pos, pos, "function body count %u mismatch (%u expected)", |
| 185 functions_count, | 183 functions_count, |
| 186 static_cast<uint32_t>(module->functions.size())); | 184 static_cast<uint32_t>(module->functions.size())); |
| 187 break; | 185 break; |
| 188 } | 186 } |
| 189 for (uint32_t i = 0; i < functions_count; ++i) { | 187 for (uint32_t i = 0; ok() && i < functions_count; ++i) { |
| 190 WasmFunction* function = &module->functions[i]; | 188 WasmFunction* function = &module->functions[i]; |
| 191 uint32_t size = consume_u32v("body size"); | 189 uint32_t size = consume_u32v("body size"); |
| 192 function->code_start_offset = pc_offset(); | 190 function->code_start_offset = pc_offset(); |
| 193 function->code_end_offset = pc_offset() + size; | 191 function->code_end_offset = pc_offset() + size; |
| 194 | 192 |
| 195 TRACE(" +%d %-20s: (%d bytes)\n", pc_offset(), "function body", | 193 TRACE(" +%d %-20s: (%d bytes)\n", pc_offset(), "function body", |
| 196 size); | 194 size); |
| 197 pc_ += size; | 195 pc_ += size; |
| 198 if (pc_ > limit_) { | 196 if (pc_ > limit_) { |
| 199 error(pc_, "function body extends beyond end of file"); | 197 error(pc_, "function body extends beyond end of file"); |
| 200 } | 198 } |
| 201 } | 199 } |
| 202 break; | 200 break; |
| 203 } | 201 } |
| 204 case WasmSection::Code::Names: { | 202 case WasmSection::Code::Names: { |
| 205 const byte* pos = pc_; | 203 const byte* pos = pc_; |
| 206 uint32_t functions_count = consume_u32v("functions count"); | 204 uint32_t functions_count = consume_u32v("functions count"); |
| 207 if (functions_count != module->functions.size()) { | 205 if (functions_count != module->functions.size()) { |
| 208 error(pos, pos, "function name count %u mismatch (%u expected)", | 206 error(pos, pos, "function name count %u mismatch (%u expected)", |
| 209 functions_count, | 207 functions_count, |
| 210 static_cast<uint32_t>(module->functions.size())); | 208 static_cast<uint32_t>(module->functions.size())); |
| 211 break; | 209 break; |
| 212 } | 210 } |
| 213 | 211 |
| 214 for (uint32_t i = 0; i < functions_count; ++i) { | 212 for (uint32_t i = 0; ok() && i < functions_count; ++i) { |
| 215 WasmFunction* function = &module->functions[i]; | 213 WasmFunction* function = &module->functions[i]; |
| 216 function->name_offset = | 214 function->name_offset = |
| 217 consume_string(&function->name_length, false); | 215 consume_string(&function->name_length, false); |
| 218 | 216 |
| 219 uint32_t local_names_count = consume_u32v("local names count"); | 217 uint32_t local_names_count = consume_u32v("local names count"); |
| 220 for (uint32_t j = 0; j < local_names_count; j++) { | 218 for (uint32_t j = 0; ok() && j < local_names_count; j++) { |
| 221 uint32_t unused = 0; | 219 uint32_t unused = 0; |
| 222 uint32_t offset = consume_string(&unused, false); | 220 uint32_t offset = consume_string(&unused, false); |
| 223 USE(unused); | 221 USE(unused); |
| 224 USE(offset); | 222 USE(offset); |
| 225 } | 223 } |
| 226 } | 224 } |
| 227 break; | 225 break; |
| 228 } | 226 } |
| 229 case WasmSection::Code::Globals: { | 227 case WasmSection::Code::Globals: { |
| 230 uint32_t globals_count = consume_u32v("globals count"); | 228 uint32_t globals_count = consume_u32v("globals count"); |
| 231 module->globals.reserve(SafeReserve(globals_count)); | 229 module->globals.reserve(SafeReserve(globals_count)); |
| 232 // Decode globals. | 230 // Decode globals. |
| 233 for (uint32_t i = 0; i < globals_count; ++i) { | 231 for (uint32_t i = 0; ok() && i < globals_count; ++i) { |
| 234 if (failed()) break; | |
| 235 TRACE("DecodeGlobal[%d] module+%d\n", i, | 232 TRACE("DecodeGlobal[%d] module+%d\n", i, |
| 236 static_cast<int>(pc_ - start_)); | 233 static_cast<int>(pc_ - start_)); |
| 237 // Add an uninitialized global and pass a pointer to it. | 234 // Add an uninitialized global and pass a pointer to it. |
| 238 module->globals.push_back({0, 0, kAstStmt, 0, false}); | 235 module->globals.push_back({0, 0, kAstStmt, 0, false}); |
| 239 WasmGlobal* global = &module->globals.back(); | 236 WasmGlobal* global = &module->globals.back(); |
| 240 DecodeGlobalInModule(global); | 237 DecodeGlobalInModule(global); |
| 241 } | 238 } |
| 242 break; | 239 break; |
| 243 } | 240 } |
| 244 case WasmSection::Code::DataSegments: { | 241 case WasmSection::Code::DataSegments: { |
| 245 uint32_t data_segments_count = consume_u32v("data segments count"); | 242 uint32_t data_segments_count = consume_u32v("data segments count"); |
| 246 module->data_segments.reserve(SafeReserve(data_segments_count)); | 243 module->data_segments.reserve(SafeReserve(data_segments_count)); |
| 247 // Decode data segments. | 244 // Decode data segments. |
| 248 for (uint32_t i = 0; i < data_segments_count; ++i) { | 245 for (uint32_t i = 0; ok() && i < data_segments_count; ++i) { |
| 249 if (failed()) break; | |
| 250 TRACE("DecodeDataSegment[%d] module+%d\n", i, | 246 TRACE("DecodeDataSegment[%d] module+%d\n", i, |
| 251 static_cast<int>(pc_ - start_)); | 247 static_cast<int>(pc_ - start_)); |
| 252 module->data_segments.push_back({0, // dest_addr | 248 module->data_segments.push_back({0, // dest_addr |
| 253 0, // source_offset | 249 0, // source_offset |
| 254 0, // source_size | 250 0, // source_size |
| 255 false}); // init | 251 false}); // init |
| 256 WasmDataSegment* segment = &module->data_segments.back(); | 252 WasmDataSegment* segment = &module->data_segments.back(); |
| 257 DecodeDataSegmentInModule(module, segment); | 253 DecodeDataSegmentInModule(module, segment); |
| 258 } | 254 } |
| 259 break; | 255 break; |
| 260 } | 256 } |
| 261 case WasmSection::Code::FunctionTable: { | 257 case WasmSection::Code::FunctionTable: { |
| 262 // An indirect function table requires functions first. | 258 // An indirect function table requires functions first. |
| 263 CheckForFunctions(module, section); | 259 CheckForFunctions(module, section); |
| 264 // Assume only one table for now. | 260 // Assume only one table for now. |
| 265 static const uint32_t kSupportedTableCount = 1; | 261 static const uint32_t kSupportedTableCount = 1; |
| 266 module->function_tables.reserve(SafeReserve(kSupportedTableCount)); | 262 module->function_tables.reserve(SafeReserve(kSupportedTableCount)); |
| 267 // Decode function table. | 263 // Decode function table. |
| 268 for (uint32_t i = 0; i < kSupportedTableCount; ++i) { | 264 for (uint32_t i = 0; ok() && i < kSupportedTableCount; ++i) { |
| 269 if (failed()) break; | |
| 270 TRACE("DecodeFunctionTable[%d] module+%d\n", i, | 265 TRACE("DecodeFunctionTable[%d] module+%d\n", i, |
| 271 static_cast<int>(pc_ - start_)); | 266 static_cast<int>(pc_ - start_)); |
| 272 module->function_tables.push_back({0, 0, std::vector<uint16_t>()}); | 267 module->function_tables.push_back({0, 0, std::vector<uint16_t>()}); |
| 273 DecodeFunctionTableInModule(module, &module->function_tables[i]); | 268 DecodeFunctionTableInModule(module, &module->function_tables[i]); |
| 274 } | 269 } |
| 275 break; | 270 break; |
| 276 } | 271 } |
| 277 case WasmSection::Code::StartFunction: { | 272 case WasmSection::Code::StartFunction: { |
| 278 // Declares a start function for a module. | 273 // Declares a start function for a module. |
| 279 CheckForFunctions(module, section); | 274 CheckForFunctions(module, section); |
| 280 if (module->start_function_index >= 0) { | 275 if (module->start_function_index >= 0) { |
| 281 error("start function already declared"); | 276 error("start function already declared"); |
| 282 break; | 277 break; |
| 283 } | 278 } |
| 284 WasmFunction* func; | 279 WasmFunction* func; |
| 285 const byte* pos = pc_; | 280 const byte* pos = pc_; |
| 286 module->start_function_index = consume_func_index(module, &func); | 281 module->start_function_index = consume_func_index(module, &func); |
| 287 if (func && func->sig->parameter_count() > 0) { | 282 if (func && func->sig->parameter_count() > 0) { |
| 288 error(pos, "invalid start function: non-zero parameter count"); | 283 error(pos, "invalid start function: non-zero parameter count"); |
| 289 break; | 284 break; |
| 290 } | 285 } |
| 291 break; | 286 break; |
| 292 } | 287 } |
| 293 case WasmSection::Code::ImportTable: { | 288 case WasmSection::Code::ImportTable: { |
| 294 uint32_t import_table_count = consume_u32v("import table count"); | 289 uint32_t import_table_count = consume_u32v("import table count"); |
| 295 module->import_table.reserve(SafeReserve(import_table_count)); | 290 module->import_table.reserve(SafeReserve(import_table_count)); |
| 296 // Decode import table. | 291 // Decode import table. |
| 297 for (uint32_t i = 0; i < import_table_count; ++i) { | 292 for (uint32_t i = 0; ok() && i < import_table_count; ++i) { |
| 298 if (failed()) break; | |
| 299 TRACE("DecodeImportTable[%d] module+%d\n", i, | 293 TRACE("DecodeImportTable[%d] module+%d\n", i, |
| 300 static_cast<int>(pc_ - start_)); | 294 static_cast<int>(pc_ - start_)); |
| 301 | 295 |
| 302 module->import_table.push_back({nullptr, // sig | 296 module->import_table.push_back({nullptr, // sig |
| 303 0, // sig_index | 297 0, // sig_index |
| 304 0, // module_name_offset | 298 0, // module_name_offset |
| 305 0, // module_name_length | 299 0, // module_name_length |
| 306 0, // function_name_offset | 300 0, // function_name_offset |
| 307 0}); // function_name_length | 301 0}); // function_name_length |
| 308 WasmImport* import = &module->import_table.back(); | 302 WasmImport* import = &module->import_table.back(); |
| 309 | 303 |
| 310 import->sig_index = consume_sig_index(module, &import->sig); | 304 import->sig_index = consume_sig_index(module, &import->sig); |
| 311 const byte* pos = pc_; | 305 const byte* pos = pc_; |
| 312 import->module_name_offset = | 306 import->module_name_offset = |
| 313 consume_string(&import->module_name_length, true); | 307 consume_string(&import->module_name_length, true); |
| 314 if (import->module_name_length == 0) { | 308 if (import->module_name_length == 0) { |
| 315 error(pos, "import module name cannot be NULL"); | 309 error(pos, "import module name cannot be NULL"); |
| 316 } | 310 } |
| 317 import->function_name_offset = | 311 import->function_name_offset = |
| 318 consume_string(&import->function_name_length, true); | 312 consume_string(&import->function_name_length, true); |
| 319 } | 313 } |
| 320 break; | 314 break; |
| 321 } | 315 } |
| 322 case WasmSection::Code::ExportTable: { | 316 case WasmSection::Code::ExportTable: { |
| 323 // Declares an export table. | 317 // Declares an export table. |
| 324 CheckForFunctions(module, section); | 318 CheckForFunctions(module, section); |
| 325 uint32_t export_table_count = consume_u32v("export table count"); | 319 uint32_t export_table_count = consume_u32v("export table count"); |
| 326 module->export_table.reserve(SafeReserve(export_table_count)); | 320 module->export_table.reserve(SafeReserve(export_table_count)); |
| 327 // Decode export table. | 321 // Decode export table. |
| 328 for (uint32_t i = 0; i < export_table_count; ++i) { | 322 for (uint32_t i = 0; ok() && i < export_table_count; ++i) { |
| 329 if (failed()) break; | |
| 330 TRACE("DecodeExportTable[%d] module+%d\n", i, | 323 TRACE("DecodeExportTable[%d] module+%d\n", i, |
| 331 static_cast<int>(pc_ - start_)); | 324 static_cast<int>(pc_ - start_)); |
| 332 | 325 |
| 333 module->export_table.push_back({0, // func_index | 326 module->export_table.push_back({0, // func_index |
| 334 0, // name_offset | 327 0, // name_offset |
| 335 0}); // name_length | 328 0}); // name_length |
| 336 WasmExport* exp = &module->export_table.back(); | 329 WasmExport* exp = &module->export_table.back(); |
| 337 | 330 |
| 338 WasmFunction* func; | 331 WasmFunction* func; |
| 339 exp->func_index = consume_func_index(module, &func); | 332 exp->func_index = consume_func_index(module, &func); |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 511 // Decodes a single function table inside a module starting at {pc_}. | 504 // Decodes a single function table inside a module starting at {pc_}. |
| 512 void DecodeFunctionTableInModule(WasmModule* module, | 505 void DecodeFunctionTableInModule(WasmModule* module, |
| 513 WasmIndirectFunctionTable* table) { | 506 WasmIndirectFunctionTable* table) { |
| 514 table->size = consume_u32v("function table entry count"); | 507 table->size = consume_u32v("function table entry count"); |
| 515 table->max_size = table->size; | 508 table->max_size = table->size; |
| 516 | 509 |
| 517 if (table->max_size != table->size) { | 510 if (table->max_size != table->size) { |
| 518 error("invalid table maximum size"); | 511 error("invalid table maximum size"); |
| 519 } | 512 } |
| 520 | 513 |
| 521 for (uint32_t i = 0; i < table->size; ++i) { | 514 for (uint32_t i = 0; ok() && i < table->size; ++i) { |
| 522 uint16_t index = consume_u32v(); | 515 uint16_t index = consume_u32v(); |
| 523 if (index >= module->functions.size()) { | 516 if (index >= module->functions.size()) { |
| 524 error(pc_ - sizeof(index), "invalid function index"); | 517 error(pc_ - sizeof(index), "invalid function index"); |
| 525 break; | 518 break; |
| 526 } | 519 } |
| 527 table->values.push_back(index); | 520 table->values.push_back(index); |
| 528 } | 521 } |
| 529 } | 522 } |
| 530 | 523 |
| 531 // Calculate individual global offsets and total size of globals table. | 524 // Calculate individual global offsets and total size of globals table. |
| (...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 821 decoder.consume_bytes(size); | 814 decoder.consume_bytes(size); |
| 822 } | 815 } |
| 823 if (decoder.more()) decoder.error("unexpected additional bytes"); | 816 if (decoder.more()) decoder.error("unexpected additional bytes"); |
| 824 | 817 |
| 825 return decoder.toResult(std::move(table)); | 818 return decoder.toResult(std::move(table)); |
| 826 } | 819 } |
| 827 | 820 |
| 828 } // namespace wasm | 821 } // namespace wasm |
| 829 } // namespace internal | 822 } // namespace internal |
| 830 } // namespace v8 | 823 } // namespace v8 |
| OLD | NEW |