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" 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 |