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/compiler-specific.h" | 8 #include "src/base/compiler-specific.h" |
9 #include "src/base/smart-pointers.h" | 9 #include "src/base/smart-pointers.h" |
10 #include "src/flags.h" | 10 #include "src/flags.h" |
(...skipping 28 matching lines...) Expand all Loading... |
39 Decoder(const byte* start, const byte* end) | 39 Decoder(const byte* start, const byte* end) |
40 : start_(start), | 40 : start_(start), |
41 pc_(start), | 41 pc_(start), |
42 limit_(end), | 42 limit_(end), |
43 end_(end), | 43 end_(end), |
44 error_pc_(nullptr), | 44 error_pc_(nullptr), |
45 error_pt_(nullptr) {} | 45 error_pt_(nullptr) {} |
46 | 46 |
47 virtual ~Decoder() {} | 47 virtual ~Decoder() {} |
48 | 48 |
49 inline bool check(const byte* base, int offset, int length, const char* msg) { | 49 inline bool check(const byte* base, unsigned offset, unsigned length, |
| 50 const char* msg) { |
50 DCHECK_GE(base, start_); | 51 DCHECK_GE(base, start_); |
51 if ((base + offset + length) > limit_) { | 52 if ((base + offset + length) > limit_) { |
52 error(base, base + offset, "%s", msg); | 53 error(base, base + offset, "%s", msg); |
53 return false; | 54 return false; |
54 } | 55 } |
55 return true; | 56 return true; |
56 } | 57 } |
57 | 58 |
58 // Reads a single 8-bit byte, reporting an error if out of bounds. | 59 // Reads a single 8-bit byte, reporting an error if out of bounds. |
59 inline uint8_t checked_read_u8(const byte* base, int offset, | 60 inline uint8_t checked_read_u8(const byte* base, unsigned offset, |
60 const char* msg = "expected 1 byte") { | 61 const char* msg = "expected 1 byte") { |
61 return check(base, offset, 1, msg) ? base[offset] : 0; | 62 return check(base, offset, 1, msg) ? base[offset] : 0; |
62 } | 63 } |
63 | 64 |
64 // Reads 16-bit word, reporting an error if out of bounds. | 65 // Reads 16-bit word, reporting an error if out of bounds. |
65 inline uint16_t checked_read_u16(const byte* base, int offset, | 66 inline uint16_t checked_read_u16(const byte* base, unsigned offset, |
66 const char* msg = "expected 2 bytes") { | 67 const char* msg = "expected 2 bytes") { |
67 return check(base, offset, 2, msg) ? read_u16(base + offset) : 0; | 68 return check(base, offset, 2, msg) ? read_u16(base + offset) : 0; |
68 } | 69 } |
69 | 70 |
70 // Reads 32-bit word, reporting an error if out of bounds. | 71 // Reads 32-bit word, reporting an error if out of bounds. |
71 inline uint32_t checked_read_u32(const byte* base, int offset, | 72 inline uint32_t checked_read_u32(const byte* base, unsigned offset, |
72 const char* msg = "expected 4 bytes") { | 73 const char* msg = "expected 4 bytes") { |
73 return check(base, offset, 4, msg) ? read_u32(base + offset) : 0; | 74 return check(base, offset, 4, msg) ? read_u32(base + offset) : 0; |
74 } | 75 } |
75 | 76 |
76 // Reads 64-bit word, reporting an error if out of bounds. | 77 // Reads 64-bit word, reporting an error if out of bounds. |
77 inline uint64_t checked_read_u64(const byte* base, int offset, | 78 inline uint64_t checked_read_u64(const byte* base, unsigned offset, |
78 const char* msg = "expected 8 bytes") { | 79 const char* msg = "expected 8 bytes") { |
79 return check(base, offset, 8, msg) ? read_u64(base + offset) : 0; | 80 return check(base, offset, 8, msg) ? read_u64(base + offset) : 0; |
80 } | 81 } |
81 | 82 |
82 // Reads a variable-length unsigned integer (little endian). | 83 // Reads a variable-length unsigned integer (little endian). |
83 uint32_t checked_read_u32v(const byte* base, int offset, int* length, | 84 uint32_t checked_read_u32v(const byte* base, unsigned offset, |
| 85 unsigned* length, |
84 const char* msg = "expected LEB32") { | 86 const char* msg = "expected LEB32") { |
85 return checked_read_leb<uint32_t, false>(base, offset, length, msg); | 87 return checked_read_leb<uint32_t, false>(base, offset, length, msg); |
86 } | 88 } |
87 | 89 |
88 // Reads a variable-length signed integer (little endian). | 90 // Reads a variable-length signed integer (little endian). |
89 int32_t checked_read_i32v(const byte* base, int offset, int* length, | 91 int32_t checked_read_i32v(const byte* base, unsigned offset, unsigned* length, |
90 const char* msg = "expected SLEB32") { | 92 const char* msg = "expected SLEB32") { |
91 uint32_t result = | 93 uint32_t result = |
92 checked_read_leb<uint32_t, true>(base, offset, length, msg); | 94 checked_read_leb<uint32_t, true>(base, offset, length, msg); |
93 if (*length == 5) return bit_cast<int32_t>(result); | 95 if (*length == 5) return bit_cast<int32_t>(result); |
94 if (*length > 0) { | 96 if (*length > 0) { |
95 int shift = 32 - 7 * *length; | 97 int shift = 32 - 7 * *length; |
96 // Perform sign extension. | 98 // Perform sign extension. |
97 return bit_cast<int32_t>(result << shift) >> shift; | 99 return bit_cast<int32_t>(result << shift) >> shift; |
98 } | 100 } |
99 return 0; | 101 return 0; |
100 } | 102 } |
101 | 103 |
102 // Reads a variable-length unsigned integer (little endian). | 104 // Reads a variable-length unsigned integer (little endian). |
103 uint64_t checked_read_u64v(const byte* base, int offset, int* length, | 105 uint64_t checked_read_u64v(const byte* base, unsigned offset, |
| 106 unsigned* length, |
104 const char* msg = "expected LEB64") { | 107 const char* msg = "expected LEB64") { |
105 return checked_read_leb<uint64_t, false>(base, offset, length, msg); | 108 return checked_read_leb<uint64_t, false>(base, offset, length, msg); |
106 } | 109 } |
107 | 110 |
108 // Reads a variable-length signed integer (little endian). | 111 // Reads a variable-length signed integer (little endian). |
109 int64_t checked_read_i64v(const byte* base, int offset, int* length, | 112 int64_t checked_read_i64v(const byte* base, unsigned offset, unsigned* length, |
110 const char* msg = "expected SLEB64") { | 113 const char* msg = "expected SLEB64") { |
111 uint64_t result = | 114 uint64_t result = |
112 checked_read_leb<uint64_t, true>(base, offset, length, msg); | 115 checked_read_leb<uint64_t, true>(base, offset, length, msg); |
113 if (*length == 10) return bit_cast<int64_t>(result); | 116 if (*length == 10) return bit_cast<int64_t>(result); |
114 if (*length > 0) { | 117 if (*length > 0) { |
115 int shift = 64 - 7 * *length; | 118 int shift = 64 - 7 * *length; |
116 // Perform sign extension. | 119 // Perform sign extension. |
117 return bit_cast<int64_t>(result << shift) >> shift; | 120 return bit_cast<int64_t>(result << shift) >> shift; |
118 } | 121 } |
119 return 0; | 122 return 0; |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
197 if (checkAvailable(4)) { | 200 if (checkAvailable(4)) { |
198 uint32_t val = read_u32(pc_); | 201 uint32_t val = read_u32(pc_); |
199 TRACE("%02x %02x %02x %02x = %u\n", pc_[0], pc_[1], pc_[2], pc_[3], val); | 202 TRACE("%02x %02x %02x %02x = %u\n", pc_[0], pc_[1], pc_[2], pc_[3], val); |
200 pc_ += 4; | 203 pc_ += 4; |
201 return val; | 204 return val; |
202 } | 205 } |
203 return traceOffEnd<uint32_t>(); | 206 return traceOffEnd<uint32_t>(); |
204 } | 207 } |
205 | 208 |
206 // Reads a LEB128 variable-length 32-bit integer and advances {pc_}. | 209 // Reads a LEB128 variable-length 32-bit integer and advances {pc_}. |
207 uint32_t consume_u32v(int* length, const char* name = nullptr) { | 210 uint32_t consume_u32v(unsigned* length, const char* name = nullptr) { |
208 TRACE(" +%d %-20s: ", static_cast<int>(pc_ - start_), | 211 TRACE(" +%d %-20s: ", static_cast<int>(pc_ - start_), |
209 name ? name : "varint"); | 212 name ? name : "varint"); |
210 | 213 |
211 if (checkAvailable(1)) { | 214 if (checkAvailable(1)) { |
212 const byte* pos = pc_; | 215 const byte* pos = pc_; |
213 const byte* end = pc_ + 5; | 216 const byte* end = pc_ + 5; |
214 if (end > limit_) end = limit_; | 217 if (end > limit_) end = limit_; |
215 | 218 |
216 uint32_t result = 0; | 219 uint32_t result = 0; |
217 int shift = 0; | 220 int shift = 0; |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
343 const byte* start_; | 346 const byte* start_; |
344 const byte* pc_; | 347 const byte* pc_; |
345 const byte* limit_; | 348 const byte* limit_; |
346 const byte* end_; | 349 const byte* end_; |
347 const byte* error_pc_; | 350 const byte* error_pc_; |
348 const byte* error_pt_; | 351 const byte* error_pt_; |
349 base::SmartArrayPointer<char> error_msg_; | 352 base::SmartArrayPointer<char> error_msg_; |
350 | 353 |
351 private: | 354 private: |
352 template <typename IntType, bool is_signed> | 355 template <typename IntType, bool is_signed> |
353 IntType checked_read_leb(const byte* base, int offset, int* length, | 356 IntType checked_read_leb(const byte* base, unsigned offset, unsigned* length, |
354 const char* msg) { | 357 const char* msg) { |
355 if (!check(base, offset, 1, msg)) { | 358 if (!check(base, offset, 1, msg)) { |
356 *length = 0; | 359 *length = 0; |
357 return 0; | 360 return 0; |
358 } | 361 } |
359 | 362 |
360 const int kMaxLength = (sizeof(IntType) * 8 + 6) / 7; | 363 const int kMaxLength = (sizeof(IntType) * 8 + 6) / 7; |
361 const byte* ptr = base + offset; | 364 const byte* ptr = base + offset; |
362 const byte* end = ptr + kMaxLength; | 365 const byte* end = ptr + kMaxLength; |
363 if (end > limit_) end = limit_; | 366 if (end > limit_) end = limit_; |
364 int shift = 0; | 367 int shift = 0; |
365 byte b = 0; | 368 byte b = 0; |
366 IntType result = 0; | 369 IntType result = 0; |
367 while (ptr < end) { | 370 while (ptr < end) { |
368 b = *ptr++; | 371 b = *ptr++; |
369 result = result | (static_cast<IntType>(b & 0x7F) << shift); | 372 result = result | (static_cast<IntType>(b & 0x7F) << shift); |
370 if ((b & 0x80) == 0) break; | 373 if ((b & 0x80) == 0) break; |
371 shift += 7; | 374 shift += 7; |
372 } | 375 } |
373 DCHECK_LE(ptr - (base + offset), kMaxLength); | 376 DCHECK_LE(ptr - (base + offset), kMaxLength); |
374 *length = static_cast<int>(ptr - (base + offset)); | 377 *length = static_cast<unsigned>(ptr - (base + offset)); |
375 if (ptr == end) { | 378 if (ptr == end) { |
376 // Check there are no bits set beyond the bitwidth of {IntType}. | 379 // Check there are no bits set beyond the bitwidth of {IntType}. |
377 const int kExtraBits = (1 + kMaxLength * 7) - (sizeof(IntType) * 8); | 380 const int kExtraBits = (1 + kMaxLength * 7) - (sizeof(IntType) * 8); |
378 const byte kExtraBitsMask = | 381 const byte kExtraBitsMask = |
379 static_cast<byte>((0xFF << (8 - kExtraBits)) & 0xFF); | 382 static_cast<byte>((0xFF << (8 - kExtraBits)) & 0xFF); |
380 int extra_bits_value; | 383 int extra_bits_value; |
381 if (is_signed) { | 384 if (is_signed) { |
382 // A signed-LEB128 must sign-extend the final byte, excluding its | 385 // A signed-LEB128 must sign-extend the final byte, excluding its |
383 // most-signifcant bit. e.g. for a 32-bit LEB128: | 386 // most-signifcant bit. e.g. for a 32-bit LEB128: |
384 // kExtraBits = 4 | 387 // kExtraBits = 4 |
(...skipping 17 matching lines...) Expand all Loading... |
402 return result; | 405 return result; |
403 } | 406 } |
404 }; | 407 }; |
405 | 408 |
406 #undef TRACE | 409 #undef TRACE |
407 } // namespace wasm | 410 } // namespace wasm |
408 } // namespace internal | 411 } // namespace internal |
409 } // namespace v8 | 412 } // namespace v8 |
410 | 413 |
411 #endif // V8_WASM_DECODER_H_ | 414 #endif // V8_WASM_DECODER_H_ |
OLD | NEW |