| 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/flags.h" | 9 #include "src/flags.h" |
| 10 #include "src/macro-assembler.h" | 10 #include "src/macro-assembler.h" |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 70 } | 70 } |
| 71 | 71 |
| 72 inline WasmSectionCode section_code() const { return section_code_; } | 72 inline WasmSectionCode section_code() const { return section_code_; } |
| 73 | 73 |
| 74 inline const byte* section_start() const { return section_start_; } | 74 inline const byte* section_start() const { return section_start_; } |
| 75 | 75 |
| 76 inline uint32_t section_length() const { | 76 inline uint32_t section_length() const { |
| 77 return static_cast<uint32_t>(section_end_ - section_start_); | 77 return static_cast<uint32_t>(section_end_ - section_start_); |
| 78 } | 78 } |
| 79 | 79 |
| 80 inline const byte* payload_start() const { return payload_start_; } |
| 81 |
| 82 inline uint32_t payload_length() const { |
| 83 return static_cast<uint32_t>(section_end_ - payload_start_); |
| 84 } |
| 85 |
| 80 inline const byte* section_end() const { return section_end_; } | 86 inline const byte* section_end() const { return section_end_; } |
| 81 | 87 |
| 82 // Advances to the next section, checking that decoding the current section | 88 // Advances to the next section, checking that decoding the current section |
| 83 // stopped at {section_end_}. | 89 // stopped at {section_end_}. |
| 84 void advance() { | 90 void advance() { |
| 85 if (decoder_.pc() != section_end_) { | 91 if (decoder_.pc() != section_end_) { |
| 86 const char* msg = decoder_.pc() < section_end_ ? "shorter" : "longer"; | 92 const char* msg = decoder_.pc() < section_end_ ? "shorter" : "longer"; |
| 87 decoder_.error(decoder_.pc(), decoder_.pc(), | 93 decoder_.error(decoder_.pc(), decoder_.pc(), |
| 88 "section was %s than expected size " | 94 "section was %s than expected size " |
| 89 "(%u bytes expected, %zu decoded)", | 95 "(%u bytes expected, %zu decoded)", |
| 90 msg, section_length(), | 96 msg, section_length(), |
| 91 static_cast<size_t>(decoder_.pc() - section_start_)); | 97 static_cast<size_t>(decoder_.pc() - section_start_)); |
| 92 } | 98 } |
| 93 next(); | 99 next(); |
| 94 } | 100 } |
| 95 | 101 |
| 96 private: | 102 private: |
| 97 Decoder& decoder_; | 103 Decoder& decoder_; |
| 98 WasmSectionCode section_code_; | 104 WasmSectionCode section_code_; |
| 99 const byte* section_start_; | 105 const byte* section_start_; |
| 106 const byte* payload_start_; |
| 100 const byte* section_end_; | 107 const byte* section_end_; |
| 101 | 108 |
| 102 // Reads the section code/name at the current position and sets up | 109 // Reads the section code/name at the current position and sets up |
| 103 // the internal fields. | 110 // the internal fields. |
| 104 void next() { | 111 void next() { |
| 105 while (true) { | 112 while (true) { |
| 106 if (!decoder_.more()) { | 113 if (!decoder_.more()) { |
| 107 section_code_ = kUnknownSectionCode; | 114 section_code_ = kUnknownSectionCode; |
| 108 return; | 115 return; |
| 109 } | 116 } |
| 110 uint8_t section_code = decoder_.consume_u8("section code"); | 117 uint8_t section_code = decoder_.consume_u8("section code"); |
| 111 // Read and check the section size. | 118 // Read and check the section size. |
| 112 uint32_t section_length = decoder_.consume_u32v("section length"); | 119 uint32_t section_length = decoder_.consume_u32v("section length"); |
| 113 section_start_ = decoder_.pc(); | 120 section_start_ = decoder_.pc(); |
| 121 payload_start_ = section_start_; |
| 114 if (decoder_.checkAvailable(section_length)) { | 122 if (decoder_.checkAvailable(section_length)) { |
| 115 // Get the limit of the section within the module. | 123 // Get the limit of the section within the module. |
| 116 section_end_ = section_start_ + section_length; | 124 section_end_ = section_start_ + section_length; |
| 117 } else { | 125 } else { |
| 118 // The section would extend beyond the end of the module. | 126 // The section would extend beyond the end of the module. |
| 119 section_end_ = section_start_; | 127 section_end_ = section_start_; |
| 120 } | 128 } |
| 121 | 129 |
| 122 if (section_code == kUnknownSectionCode) { | 130 if (section_code == kUnknownSectionCode) { |
| 123 // Check for the known "names" section. | 131 // Check for the known "name" or "asm_offsets" section. |
| 124 uint32_t string_length = decoder_.consume_u32v("section name length"); | 132 uint32_t string_length = decoder_.consume_u32v("section name length"); |
| 125 const byte* section_name_start = decoder_.pc(); | 133 const byte* section_name_start = decoder_.pc(); |
| 126 decoder_.consume_bytes(string_length, "section name"); | 134 decoder_.consume_bytes(string_length, "section name"); |
| 127 if (decoder_.failed() || decoder_.pc() > section_end_) { | 135 if (decoder_.failed() || decoder_.pc() > section_end_) { |
| 128 TRACE("Section name of length %u couldn't be read\n", string_length); | 136 TRACE("Section name of length %u couldn't be read\n", string_length); |
| 129 section_code_ = kUnknownSectionCode; | 137 section_code_ = kUnknownSectionCode; |
| 130 return; | 138 return; |
| 131 } | 139 } |
| 140 payload_start_ = decoder_.pc(); |
| 132 | 141 |
| 133 TRACE(" +%d section name : \"%.*s\"\n", | 142 TRACE(" +%d section name : \"%.*s\"\n", |
| 134 static_cast<int>(section_name_start - decoder_.start()), | 143 static_cast<int>(section_name_start - decoder_.start()), |
| 135 string_length < 20 ? string_length : 20, section_name_start); | 144 string_length < 20 ? string_length : 20, section_name_start); |
| 136 | 145 |
| 137 if (string_length == kNameStringLength && | 146 if (string_length == kNameStringLength && |
| 138 strncmp(reinterpret_cast<const char*>(section_name_start), | 147 strncmp(reinterpret_cast<const char*>(section_name_start), |
| 139 kNameString, kNameStringLength) == 0) { | 148 kNameString, kNameStringLength) == 0) { |
| 140 section_code = kNameSectionCode; | 149 section_code = kNameSectionCode; |
| 141 } else { | 150 } else { |
| (...skipping 441 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 583 functions_count, module->num_declared_functions); | 592 functions_count, module->num_declared_functions); |
| 584 } | 593 } |
| 585 | 594 |
| 586 for (uint32_t i = 0; ok() && i < functions_count; ++i) { | 595 for (uint32_t i = 0; ok() && i < functions_count; ++i) { |
| 587 WasmFunction* function = | 596 WasmFunction* function = |
| 588 &module->functions[i + module->num_imported_functions]; | 597 &module->functions[i + module->num_imported_functions]; |
| 589 function->name_offset = consume_string(&function->name_length, false); | 598 function->name_offset = consume_string(&function->name_length, false); |
| 590 | 599 |
| 591 uint32_t local_names_count = consume_u32v("local names count"); | 600 uint32_t local_names_count = consume_u32v("local names count"); |
| 592 for (uint32_t j = 0; ok() && j < local_names_count; j++) { | 601 for (uint32_t j = 0; ok() && j < local_names_count; j++) { |
| 593 uint32_t unused = 0; | 602 skip_string(); |
| 594 uint32_t offset = consume_string(&unused, false); | |
| 595 USE(unused); | |
| 596 USE(offset); | |
| 597 } | 603 } |
| 598 } | 604 } |
| 599 section_iter.advance(); | 605 section_iter.advance(); |
| 600 } | 606 } |
| 601 | 607 |
| 602 // ===== Remaining sections ============================================== | 608 // ===== Remaining sections ============================================== |
| 603 if (section_iter.more() && ok()) { | 609 if (section_iter.more() && ok()) { |
| 604 error(pc(), pc(), "unexpected section: %s", | 610 error(pc(), pc(), "unexpected section: %s", |
| 605 SectionName(section_iter.section_code())); | 611 SectionName(section_iter.section_code())); |
| 606 } | 612 } |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 792 const byte* string_start = pc_; | 798 const byte* string_start = pc_; |
| 793 // Consume bytes before validation to guarantee that the string is not oob. | 799 // Consume bytes before validation to guarantee that the string is not oob. |
| 794 if (*length > 0) consume_bytes(*length, "string"); | 800 if (*length > 0) consume_bytes(*length, "string"); |
| 795 if (ok() && validate_utf8 && | 801 if (ok() && validate_utf8 && |
| 796 !unibrow::Utf8::Validate(string_start, *length)) { | 802 !unibrow::Utf8::Validate(string_start, *length)) { |
| 797 error(string_start, "no valid UTF-8 string"); | 803 error(string_start, "no valid UTF-8 string"); |
| 798 } | 804 } |
| 799 return offset; | 805 return offset; |
| 800 } | 806 } |
| 801 | 807 |
| 808 // Skips over a length-prefixed string, but checks that it is within bounds. |
| 809 void skip_string() { |
| 810 uint32_t length = consume_u32v("string length"); |
| 811 consume_bytes(length, "string"); |
| 812 } |
| 813 |
| 802 uint32_t consume_sig_index(WasmModule* module, FunctionSig** sig) { | 814 uint32_t consume_sig_index(WasmModule* module, FunctionSig** sig) { |
| 803 const byte* pos = pc_; | 815 const byte* pos = pc_; |
| 804 uint32_t sig_index = consume_u32v("signature index"); | 816 uint32_t sig_index = consume_u32v("signature index"); |
| 805 if (sig_index >= module->signatures.size()) { | 817 if (sig_index >= module->signatures.size()) { |
| 806 error(pos, pos, "signature index %u out of bounds (%d signatures)", | 818 error(pos, pos, "signature index %u out of bounds (%d signatures)", |
| 807 sig_index, static_cast<int>(module->signatures.size())); | 819 sig_index, static_cast<int>(module->signatures.size())); |
| 808 *sig = nullptr; | 820 *sig = nullptr; |
| 809 return 0; | 821 return 0; |
| 810 } | 822 } |
| 811 *sig = module->signatures[sig_index]; | 823 *sig = module->signatures[sig_index]; |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1022 explicit FunctionError(const char* msg) { | 1034 explicit FunctionError(const char* msg) { |
| 1023 error_code = kError; | 1035 error_code = kError; |
| 1024 size_t len = strlen(msg) + 1; | 1036 size_t len = strlen(msg) + 1; |
| 1025 char* result = new char[len]; | 1037 char* result = new char[len]; |
| 1026 strncpy(result, msg, len); | 1038 strncpy(result, msg, len); |
| 1027 result[len - 1] = 0; | 1039 result[len - 1] = 0; |
| 1028 error_msg.reset(result); | 1040 error_msg.reset(result); |
| 1029 } | 1041 } |
| 1030 }; | 1042 }; |
| 1031 | 1043 |
| 1044 // Find section with given section code. Return Vector of the payload, or null |
| 1045 // Vector if section is not found or module bytes are invalid. |
| 1032 Vector<const byte> FindSection(const byte* module_start, const byte* module_end, | 1046 Vector<const byte> FindSection(const byte* module_start, const byte* module_end, |
| 1033 WasmSectionCode code) { | 1047 WasmSectionCode code) { |
| 1034 Decoder decoder(module_start, module_end); | 1048 Decoder decoder(module_start, module_end); |
| 1035 | 1049 |
| 1036 uint32_t magic_word = decoder.consume_u32("wasm magic"); | 1050 uint32_t magic_word = decoder.consume_u32("wasm magic"); |
| 1037 if (magic_word != kWasmMagic) decoder.error("wrong magic word"); | 1051 if (magic_word != kWasmMagic) decoder.error("wrong magic word"); |
| 1038 | 1052 |
| 1039 uint32_t magic_version = decoder.consume_u32("wasm version"); | 1053 uint32_t magic_version = decoder.consume_u32("wasm version"); |
| 1040 if (magic_version != kWasmVersion) decoder.error("wrong wasm version"); | 1054 if (magic_version != kWasmVersion) decoder.error("wrong wasm version"); |
| 1041 | 1055 |
| 1042 WasmSectionIterator section_iter(decoder); | 1056 WasmSectionIterator section_iter(decoder); |
| 1043 while (section_iter.more()) { | 1057 while (section_iter.more()) { |
| 1044 if (section_iter.section_code() == code) { | 1058 if (section_iter.section_code() == code) { |
| 1045 return Vector<const uint8_t>(section_iter.section_start(), | 1059 return Vector<const uint8_t>(section_iter.payload_start(), |
| 1046 section_iter.section_length()); | 1060 section_iter.payload_length()); |
| 1047 } | 1061 } |
| 1048 decoder.consume_bytes(section_iter.section_length(), "section payload"); | 1062 decoder.consume_bytes(section_iter.payload_length(), "section payload"); |
| 1049 section_iter.advance(); | 1063 section_iter.advance(); |
| 1050 } | 1064 } |
| 1051 | 1065 |
| 1052 return Vector<const uint8_t>(); | 1066 return Vector<const uint8_t>(); |
| 1053 } | 1067 } |
| 1054 | 1068 |
| 1055 } // namespace | 1069 } // namespace |
| 1056 | 1070 |
| 1057 ModuleResult DecodeWasmModule(Isolate* isolate, Zone* zone, | 1071 ModuleResult DecodeWasmModule(Isolate* isolate, Zone* zone, |
| 1058 const byte* module_start, const byte* module_end, | 1072 const byte* module_start, const byte* module_end, |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1111 // Find and decode the code section. | 1125 // Find and decode the code section. |
| 1112 Vector<const byte> code_section = | 1126 Vector<const byte> code_section = |
| 1113 FindSection(module_start, module_end, kCodeSectionCode); | 1127 FindSection(module_start, module_end, kCodeSectionCode); |
| 1114 Decoder decoder(code_section.start(), code_section.end()); | 1128 Decoder decoder(code_section.start(), code_section.end()); |
| 1115 FunctionOffsets table; | 1129 FunctionOffsets table; |
| 1116 if (!code_section.start()) { | 1130 if (!code_section.start()) { |
| 1117 decoder.error("no code section"); | 1131 decoder.error("no code section"); |
| 1118 return decoder.toResult(std::move(table)); | 1132 return decoder.toResult(std::move(table)); |
| 1119 } | 1133 } |
| 1120 | 1134 |
| 1121 // Reserve entries for the imported functions. | 1135 uint32_t functions_count = decoder.consume_u32v("functions count"); |
| 1122 table.reserve(num_imported_functions); | 1136 // Reserve space for the entries, taking care of invalid input. |
| 1123 for (uint32_t i = 0; i < num_imported_functions; i++) { | 1137 if (functions_count < static_cast<unsigned>(code_section.length()) / 2) { |
| 1124 table.push_back(std::make_pair(0, 0)); | 1138 table.reserve(num_imported_functions + functions_count); |
| 1125 } | 1139 } |
| 1126 | 1140 |
| 1127 uint32_t functions_count = decoder.consume_u32v("functions count"); | 1141 // Add null entries for the imported functions. |
| 1128 // Take care of invalid input here. | 1142 table.resize(num_imported_functions); |
| 1129 if (functions_count < static_cast<unsigned>(code_section.length()) / 2) | 1143 |
| 1130 table.reserve(num_imported_functions + functions_count); | |
| 1131 int section_offset = static_cast<int>(code_section.start() - module_start); | 1144 int section_offset = static_cast<int>(code_section.start() - module_start); |
| 1132 DCHECK_LE(0, section_offset); | 1145 DCHECK_LE(0, section_offset); |
| 1133 for (uint32_t i = 0; i < functions_count && decoder.ok(); ++i) { | 1146 for (uint32_t i = 0; i < functions_count && decoder.ok(); ++i) { |
| 1134 uint32_t size = decoder.consume_u32v("body size"); | 1147 uint32_t size = decoder.consume_u32v("body size"); |
| 1135 int offset = static_cast<int>(section_offset + decoder.pc_offset()); | 1148 int offset = static_cast<int>(section_offset + decoder.pc_offset()); |
| 1136 table.push_back(std::make_pair(offset, static_cast<int>(size))); | 1149 table.push_back(std::make_pair(offset, static_cast<int>(size))); |
| 1137 DCHECK(table.back().first >= 0 && table.back().second >= 0); | 1150 DCHECK(table.back().first >= 0 && table.back().second >= 0); |
| 1138 decoder.consume_bytes(size); | 1151 decoder.consume_bytes(size); |
| 1139 } | 1152 } |
| 1140 if (decoder.more()) decoder.error("unexpected additional bytes"); | 1153 if (decoder.more()) decoder.error("unexpected additional bytes"); |
| 1141 | 1154 |
| 1142 return decoder.toResult(std::move(table)); | 1155 return decoder.toResult(std::move(table)); |
| 1143 } | 1156 } |
| 1144 | 1157 |
| 1158 AsmJsOffsetsResult DecodeAsmJsOffsets(const byte* tables_start, |
| 1159 const byte* tables_end, |
| 1160 uint32_t num_imported_functions) { |
| 1161 AsmJsOffsets table; |
| 1162 |
| 1163 Decoder decoder(tables_start, tables_end); |
| 1164 uint32_t functions_count = decoder.consume_u32v("functions count"); |
| 1165 // Reserve space for the entries, taking care of invalid input. |
| 1166 if (functions_count < static_cast<unsigned>(tables_end - tables_start)) { |
| 1167 table.reserve(num_imported_functions + functions_count); |
| 1168 } |
| 1169 |
| 1170 // Add null entries for the imported functions. |
| 1171 table.resize(num_imported_functions); |
| 1172 |
| 1173 for (uint32_t i = 0; i < functions_count && decoder.ok(); ++i) { |
| 1174 uint32_t size = decoder.consume_u32v("table size"); |
| 1175 if (size == 0) { |
| 1176 table.push_back(std::vector<std::pair<int, int>>()); |
| 1177 continue; |
| 1178 } |
| 1179 if (!decoder.checkAvailable(size)) { |
| 1180 decoder.error("illegal asm function offset table size"); |
| 1181 } |
| 1182 const byte* table_end = decoder.pc() + size; |
| 1183 uint32_t locals_size = decoder.consume_u32("locals size"); |
| 1184 int last_byte_offset = locals_size; |
| 1185 int last_asm_position = 0; |
| 1186 std::vector<std::pair<int, int>> func_asm_offsets; |
| 1187 func_asm_offsets.reserve(size / 4); // conservative estimation |
| 1188 while (decoder.ok() && decoder.pc() < table_end) { |
| 1189 last_byte_offset += decoder.consume_u32v("byte offset delta"); |
| 1190 last_asm_position += decoder.consume_i32v("asm position delta"); |
| 1191 func_asm_offsets.push_back({last_byte_offset, last_asm_position}); |
| 1192 } |
| 1193 if (decoder.pc() != table_end) { |
| 1194 decoder.error("broken asm offset table"); |
| 1195 } |
| 1196 table.push_back(std::move(func_asm_offsets)); |
| 1197 } |
| 1198 if (decoder.more()) decoder.error("unexpected additional bytes"); |
| 1199 |
| 1200 return decoder.toResult(std::move(table)); |
| 1201 } |
| 1202 |
| 1145 } // namespace wasm | 1203 } // namespace wasm |
| 1146 } // namespace internal | 1204 } // namespace internal |
| 1147 } // namespace v8 | 1205 } // namespace v8 |
| OLD | NEW |