| 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 #ifndef V8_WASM_DECODER_H_ | 5 #ifndef V8_WASM_DECODER_H_ | 
| 6 #define V8_WASM_DECODER_H_ | 6 #define V8_WASM_DECODER_H_ | 
| 7 | 7 | 
| 8 #include "src/base/smart-pointers.h" | 8 #include "src/base/smart-pointers.h" | 
| 9 #include "src/flags.h" | 9 #include "src/flags.h" | 
| 10 #include "src/signature.h" | 10 #include "src/signature.h" | 
| 11 #include "src/wasm/wasm-result.h" | 11 #include "src/wasm/wasm-result.h" | 
| 12 #include "src/zone-containers.h" | 12 #include "src/zone-containers.h" | 
| 13 | 13 | 
| 14 namespace v8 { | 14 namespace v8 { | 
| 15 namespace internal { | 15 namespace internal { | 
| 16 namespace wasm { | 16 namespace wasm { | 
| 17 | 17 | 
| 18 #if DEBUG | 18 #if DEBUG | 
| 19 #define TRACE(...)                                    \ | 19 #define TRACE(...)                                    \ | 
| 20   do {                                                \ | 20   do {                                                \ | 
| 21     if (FLAG_trace_wasm_decoder) PrintF(__VA_ARGS__); \ | 21     if (FLAG_trace_wasm_decoder) PrintF(__VA_ARGS__); \ | 
| 22   } while (false) | 22   } while (false) | 
| 23 #else | 23 #else | 
| 24 #define TRACE(...) | 24 #define TRACE(...) | 
| 25 #endif | 25 #endif | 
| 26 | 26 | 
|  | 27 #if !(V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_ARM) | 
|  | 28 #define UNALIGNED_ACCESS_OK 1 | 
|  | 29 #else | 
|  | 30 #define UNALIGNED_ACCESS_OK 0 | 
|  | 31 #endif | 
|  | 32 | 
| 27 // A helper utility to decode bytes, integers, fields, varints, etc, from | 33 // A helper utility to decode bytes, integers, fields, varints, etc, from | 
| 28 // a buffer of bytes. | 34 // a buffer of bytes. | 
| 29 class Decoder { | 35 class Decoder { | 
| 30  public: | 36  public: | 
| 31   Decoder(const byte* start, const byte* end) | 37   Decoder(const byte* start, const byte* end) | 
| 32       : start_(start), | 38       : start_(start), | 
| 33         pc_(start), | 39         pc_(start), | 
| 34         limit_(end), | 40         limit_(end), | 
|  | 41         end_(end), | 
| 35         error_pc_(nullptr), | 42         error_pc_(nullptr), | 
| 36         error_pt_(nullptr) {} | 43         error_pt_(nullptr) {} | 
| 37 | 44 | 
| 38   virtual ~Decoder() {} | 45   virtual ~Decoder() {} | 
| 39 | 46 | 
|  | 47   // Reads a single 16-bit unsigned integer (little endian). | 
|  | 48   inline uint16_t read_u16(const byte* ptr) { | 
|  | 49     DCHECK(ptr >= start_ && (ptr + 2) <= end_); | 
|  | 50 #if V8_TARGET_LITTLE_ENDIAN && UNALIGNED_ACCESS_OK | 
|  | 51     return *reinterpret_cast<const uint16_t*>(ptr); | 
|  | 52 #else | 
|  | 53     uint16_t b0 = ptr[0]; | 
|  | 54     uint16_t b1 = ptr[1]; | 
|  | 55     return (b1 << 8) | b0; | 
|  | 56 #endif | 
|  | 57   } | 
|  | 58 | 
|  | 59   // Reads a single 32-bit unsigned integer (little endian). | 
|  | 60   inline uint32_t read_u32(const byte* ptr) { | 
|  | 61     DCHECK(ptr >= start_ && (ptr + 4) <= end_); | 
|  | 62 #if V8_TARGET_LITTLE_ENDIAN && UNALIGNED_ACCESS_OK | 
|  | 63     return *reinterpret_cast<const uint32_t*>(ptr); | 
|  | 64 #else | 
|  | 65     uint32_t b0 = ptr[0]; | 
|  | 66     uint32_t b1 = ptr[1]; | 
|  | 67     uint32_t b2 = ptr[2]; | 
|  | 68     uint32_t b3 = ptr[3]; | 
|  | 69     return (b3 << 24) | (b2 << 16) | (b1 << 8) | b0; | 
|  | 70 #endif | 
|  | 71   } | 
|  | 72 | 
|  | 73   // Reads a single 64-bit unsigned integer (little endian). | 
|  | 74   inline uint64_t read_u64(const byte* ptr) { | 
|  | 75     DCHECK(ptr >= start_ && (ptr + 8) <= end_); | 
|  | 76 #if V8_TARGET_LITTLE_ENDIAN && UNALIGNED_ACCESS_OK | 
|  | 77     return *reinterpret_cast<const uint64_t*>(ptr); | 
|  | 78 #else | 
|  | 79     uint32_t b0 = ptr[0]; | 
|  | 80     uint32_t b1 = ptr[1]; | 
|  | 81     uint32_t b2 = ptr[2]; | 
|  | 82     uint32_t b3 = ptr[3]; | 
|  | 83     uint32_t low = (b3 << 24) | (b2 << 16) | (b1 << 8) | b0; | 
|  | 84     uint32_t b4 = ptr[4]; | 
|  | 85     uint32_t b5 = ptr[5]; | 
|  | 86     uint32_t b6 = ptr[6]; | 
|  | 87     uint32_t b7 = ptr[7]; | 
|  | 88     uint64_t high = (b7 << 24) | (b6 << 16) | (b5 << 8) | b4; | 
|  | 89     return (high << 32) | low; | 
|  | 90 #endif | 
|  | 91   } | 
|  | 92 | 
| 40   // Reads a 8-bit unsigned integer (byte) and advances {pc_}. | 93   // Reads a 8-bit unsigned integer (byte) and advances {pc_}. | 
| 41   uint8_t u8(const char* name = nullptr) { | 94   uint8_t consume_u8(const char* name = nullptr) { | 
| 42     TRACE("  +%d  %-20s: ", static_cast<int>(pc_ - start_), | 95     TRACE("  +%d  %-20s: ", static_cast<int>(pc_ - start_), | 
| 43           name ? name : "uint8_t"); | 96           name ? name : "uint8_t"); | 
| 44     if (checkAvailable(1)) { | 97     if (checkAvailable(1)) { | 
| 45       byte val = *(pc_++); | 98       byte val = *(pc_++); | 
| 46       TRACE("%02x = %d\n", val, val); | 99       TRACE("%02x = %d\n", val, val); | 
| 47       return val; | 100       return val; | 
| 48     } else { |  | 
| 49       error("expected 1 byte, but fell off end"); |  | 
| 50       return traceOffEnd<uint8_t>(); |  | 
| 51     } | 101     } | 
|  | 102     return traceOffEnd<uint8_t>(); | 
| 52   } | 103   } | 
| 53 | 104 | 
| 54   // Reads a 16-bit unsigned integer (little endian) and advances {pc_}. | 105   // Reads a 16-bit unsigned integer (little endian) and advances {pc_}. | 
| 55   uint16_t u16(const char* name = nullptr) { | 106   uint16_t consume_u16(const char* name = nullptr) { | 
| 56     TRACE("  +%d  %-20s: ", static_cast<int>(pc_ - start_), | 107     TRACE("  +%d  %-20s: ", static_cast<int>(pc_ - start_), | 
| 57           name ? name : "uint16_t"); | 108           name ? name : "uint16_t"); | 
| 58     if (checkAvailable(2)) { | 109     if (checkAvailable(2)) { | 
| 59 #ifdef V8_TARGET_LITTLE_ENDIAN | 110       uint16_t val = read_u16(pc_); | 
| 60       byte b0 = pc_[0]; |  | 
| 61       byte b1 = pc_[1]; |  | 
| 62 #else |  | 
| 63       byte b1 = pc_[0]; |  | 
| 64       byte b0 = pc_[1]; |  | 
| 65 #endif |  | 
| 66       uint16_t val = static_cast<uint16_t>(b1 << 8) | b0; |  | 
| 67       TRACE("%02x %02x = %d\n", pc_[0], pc_[1], val); | 111       TRACE("%02x %02x = %d\n", pc_[0], pc_[1], val); | 
| 68       pc_ += 2; | 112       pc_ += 2; | 
| 69       return val; | 113       return val; | 
| 70     } else { |  | 
| 71       error("expected 2 bytes, but fell off end"); |  | 
| 72       return traceOffEnd<uint16_t>(); |  | 
| 73     } | 114     } | 
|  | 115     return traceOffEnd<uint16_t>(); | 
| 74   } | 116   } | 
| 75 | 117 | 
| 76   // Reads a single 32-bit unsigned integer (little endian) and advances {pc_}. | 118   // Reads a single 32-bit unsigned integer (little endian) and advances {pc_}. | 
| 77   uint32_t u32(const char* name = nullptr) { | 119   uint32_t consume_u32(const char* name = nullptr) { | 
| 78     TRACE("  +%d  %-20s: ", static_cast<int>(pc_ - start_), | 120     TRACE("  +%d  %-20s: ", static_cast<int>(pc_ - start_), | 
| 79           name ? name : "uint32_t"); | 121           name ? name : "uint32_t"); | 
| 80     if (checkAvailable(4)) { | 122     if (checkAvailable(4)) { | 
| 81 #ifdef V8_TARGET_LITTLE_ENDIAN | 123       uint32_t val = read_u32(pc_); | 
| 82       byte b0 = pc_[0]; |  | 
| 83       byte b1 = pc_[1]; |  | 
| 84       byte b2 = pc_[2]; |  | 
| 85       byte b3 = pc_[3]; |  | 
| 86 #else |  | 
| 87       byte b3 = pc_[0]; |  | 
| 88       byte b2 = pc_[1]; |  | 
| 89       byte b1 = pc_[2]; |  | 
| 90       byte b0 = pc_[3]; |  | 
| 91 #endif |  | 
| 92       uint32_t val = static_cast<uint32_t>(b3 << 24) | |  | 
| 93                      static_cast<uint32_t>(b2 << 16) | |  | 
| 94                      static_cast<uint32_t>(b1 << 8) | b0; |  | 
| 95       TRACE("%02x %02x %02x %02x = %u\n", pc_[0], pc_[1], pc_[2], pc_[3], val); | 124       TRACE("%02x %02x %02x %02x = %u\n", pc_[0], pc_[1], pc_[2], pc_[3], val); | 
| 96       pc_ += 4; | 125       pc_ += 4; | 
| 97       return val; | 126       return val; | 
| 98     } else { |  | 
| 99       error("expected 4 bytes, but fell off end"); |  | 
| 100       return traceOffEnd<uint32_t>(); |  | 
| 101     } | 127     } | 
|  | 128     return traceOffEnd<uint32_t>(); | 
| 102   } | 129   } | 
| 103 | 130 | 
| 104   // Reads a LEB128 variable-length 32-bit integer and advances {pc_}. | 131   // Reads a LEB128 variable-length 32-bit integer and advances {pc_}. | 
| 105   uint32_t u32v(int* length, const char* name = nullptr) { | 132   uint32_t consume_u32v(int* length, const char* name = nullptr) { | 
| 106     TRACE("  +%d  %-20s: ", static_cast<int>(pc_ - start_), | 133     TRACE("  +%d  %-20s: ", static_cast<int>(pc_ - start_), | 
| 107           name ? name : "varint"); | 134           name ? name : "varint"); | 
| 108 | 135 | 
| 109     if (!checkAvailable(1)) { | 136     if (checkAvailable(1)) { | 
| 110       error("expected at least 1 byte, but fell off end"); | 137       const byte* pos = pc_; | 
| 111       return traceOffEnd<uint32_t>(); | 138       const byte* end = pc_ + 5; | 
|  | 139       if (end > limit_) end = limit_; | 
|  | 140 | 
|  | 141       uint32_t result = 0; | 
|  | 142       int shift = 0; | 
|  | 143       byte b = 0; | 
|  | 144       while (pc_ < end) { | 
|  | 145         b = *pc_++; | 
|  | 146         TRACE("%02x ", b); | 
|  | 147         result = result | ((b & 0x7F) << shift); | 
|  | 148         if ((b & 0x80) == 0) break; | 
|  | 149         shift += 7; | 
|  | 150       } | 
|  | 151 | 
|  | 152       *length = static_cast<int>(pc_ - pos); | 
|  | 153       if (pc_ == end && (b & 0x80)) { | 
|  | 154         error(pc_ - 1, "varint too large"); | 
|  | 155       } else { | 
|  | 156         TRACE("= %u\n", result); | 
|  | 157       } | 
|  | 158       return result; | 
| 112     } | 159     } | 
| 113 | 160     return traceOffEnd<uint32_t>(); | 
| 114     const byte* pos = pc_; |  | 
| 115     const byte* end = pc_ + 5; |  | 
| 116     if (end > limit_) end = limit_; |  | 
| 117 |  | 
| 118     uint32_t result = 0; |  | 
| 119     int shift = 0; |  | 
| 120     byte b = 0; |  | 
| 121     while (pc_ < end) { |  | 
| 122       b = *pc_++; |  | 
| 123       TRACE("%02x ", b); |  | 
| 124       result = result | ((b & 0x7F) << shift); |  | 
| 125       if ((b & 0x80) == 0) break; |  | 
| 126       shift += 7; |  | 
| 127     } |  | 
| 128 |  | 
| 129     *length = static_cast<int>(pc_ - pos); |  | 
| 130     if (pc_ == end && (b & 0x80)) { |  | 
| 131       error(pc_ - 1, "varint too large"); |  | 
| 132     } else { |  | 
| 133       TRACE("= %u\n", result); |  | 
| 134     } |  | 
| 135     return result; |  | 
| 136   } | 161   } | 
| 137 | 162 | 
| 138   // Check that at least {size} bytes exist between {pc_} and {limit_}. | 163   // Check that at least {size} bytes exist between {pc_} and {limit_}. | 
| 139   bool checkAvailable(int size) { | 164   bool checkAvailable(int size) { | 
| 140     if (pc_ < start_ || (pc_ + size) > limit_) { | 165     if (pc_ < start_ || (pc_ + size) > limit_) { | 
| 141       error(pc_, nullptr, "expected %d bytes, fell off end", size); | 166       error(pc_, nullptr, "expected %d bytes, fell off end", size); | 
| 142       return false; | 167       return false; | 
| 143     } else { | 168     } else { | 
| 144       return true; | 169       return true; | 
| 145     } | 170     } | 
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 201     } | 226     } | 
| 202     result.val = val; | 227     result.val = val; | 
| 203     return result; | 228     return result; | 
| 204   } | 229   } | 
| 205 | 230 | 
| 206   // Resets the boundaries of this decoder. | 231   // Resets the boundaries of this decoder. | 
| 207   void Reset(const byte* start, const byte* end) { | 232   void Reset(const byte* start, const byte* end) { | 
| 208     start_ = start; | 233     start_ = start; | 
| 209     pc_ = start; | 234     pc_ = start; | 
| 210     limit_ = end; | 235     limit_ = end; | 
|  | 236     end_ = end; | 
| 211     error_pc_ = nullptr; | 237     error_pc_ = nullptr; | 
| 212     error_pt_ = nullptr; | 238     error_pt_ = nullptr; | 
| 213     error_msg_.Reset(nullptr); | 239     error_msg_.Reset(nullptr); | 
| 214   } | 240   } | 
| 215 | 241 | 
| 216   bool ok() const { return error_pc_ == nullptr; } | 242   bool ok() const { return error_pc_ == nullptr; } | 
| 217   bool failed() const { return error_pc_ != nullptr; } | 243   bool failed() const { return error_pc_ != nullptr; } | 
| 218 | 244 | 
| 219  protected: | 245  protected: | 
| 220   const byte* start_; | 246   const byte* start_; | 
| 221   const byte* pc_; | 247   const byte* pc_; | 
| 222   const byte* limit_; | 248   const byte* limit_; | 
|  | 249   const byte* end_; | 
| 223   const byte* error_pc_; | 250   const byte* error_pc_; | 
| 224   const byte* error_pt_; | 251   const byte* error_pt_; | 
| 225   base::SmartArrayPointer<char> error_msg_; | 252   base::SmartArrayPointer<char> error_msg_; | 
| 226 }; | 253 }; | 
| 227 | 254 | 
| 228 #undef TRACE | 255 #undef TRACE | 
| 229 }  // namespace wasm | 256 }  // namespace wasm | 
| 230 }  // namespace internal | 257 }  // namespace internal | 
| 231 }  // namespace v8 | 258 }  // namespace v8 | 
| 232 | 259 | 
| 233 #endif  // V8_WASM_DECODER_H_ | 260 #endif  // V8_WASM_DECODER_H_ | 
| OLD | NEW | 
|---|