Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(9)

Side by Side Diff: src/wasm/decoder.h

Issue 2052623003: [wasm] improve handling of malformed input (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: add overflow check to BranchTableOperand Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698