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

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: rebase Created 4 years, 5 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
« no previous file with comments | « src/wasm/ast-decoder.cc ('k') | test/unittests/wasm/decoder-unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
342 const byte* start_; 345 const byte* start_;
343 const byte* pc_; 346 const byte* pc_;
344 const byte* limit_; 347 const byte* limit_;
345 const byte* end_; 348 const byte* end_;
346 const byte* error_pc_; 349 const byte* error_pc_;
347 const byte* error_pt_; 350 const byte* error_pt_;
348 base::SmartArrayPointer<char> error_msg_; 351 base::SmartArrayPointer<char> error_msg_;
349 352
350 private: 353 private:
351 template <typename IntType, bool is_signed> 354 template <typename IntType, bool is_signed>
352 IntType checked_read_leb(const byte* base, int offset, int* length, 355 IntType checked_read_leb(const byte* base, unsigned offset, unsigned* length,
353 const char* msg) { 356 const char* msg) {
354 if (!check(base, offset, 1, msg)) { 357 if (!check(base, offset, 1, msg)) {
355 *length = 0; 358 *length = 0;
356 return 0; 359 return 0;
357 } 360 }
358 361
359 const int kMaxLength = (sizeof(IntType) * 8 + 6) / 7; 362 const int kMaxLength = (sizeof(IntType) * 8 + 6) / 7;
360 const byte* ptr = base + offset; 363 const byte* ptr = base + offset;
361 const byte* end = ptr + kMaxLength; 364 const byte* end = ptr + kMaxLength;
362 if (end > limit_) end = limit_; 365 if (end > limit_) end = limit_;
363 int shift = 0; 366 int shift = 0;
364 byte b = 0; 367 byte b = 0;
365 IntType result = 0; 368 IntType result = 0;
366 while (ptr < end) { 369 while (ptr < end) {
367 b = *ptr++; 370 b = *ptr++;
368 result = result | (static_cast<IntType>(b & 0x7F) << shift); 371 result = result | (static_cast<IntType>(b & 0x7F) << shift);
369 if ((b & 0x80) == 0) break; 372 if ((b & 0x80) == 0) break;
370 shift += 7; 373 shift += 7;
371 } 374 }
372 DCHECK_LE(ptr - (base + offset), kMaxLength); 375 DCHECK_LE(ptr - (base + offset), kMaxLength);
373 *length = static_cast<int>(ptr - (base + offset)); 376 *length = static_cast<unsigned>(ptr - (base + offset));
374 if (ptr == end) { 377 if (ptr == end) {
375 // Check there are no bits set beyond the bitwidth of {IntType}. 378 // Check there are no bits set beyond the bitwidth of {IntType}.
376 const int kExtraBits = (1 + kMaxLength * 7) - (sizeof(IntType) * 8); 379 const int kExtraBits = (1 + kMaxLength * 7) - (sizeof(IntType) * 8);
377 const byte kExtraBitsMask = 380 const byte kExtraBitsMask =
378 static_cast<byte>((0xFF << (8 - kExtraBits)) & 0xFF); 381 static_cast<byte>((0xFF << (8 - kExtraBits)) & 0xFF);
379 int extra_bits_value; 382 int extra_bits_value;
380 if (is_signed) { 383 if (is_signed) {
381 // A signed-LEB128 must sign-extend the final byte, excluding its 384 // A signed-LEB128 must sign-extend the final byte, excluding its
382 // most-signifcant bit. e.g. for a 32-bit LEB128: 385 // most-signifcant bit. e.g. for a 32-bit LEB128:
383 // kExtraBits = 4 386 // kExtraBits = 4
(...skipping 17 matching lines...) Expand all
401 return result; 404 return result;
402 } 405 }
403 }; 406 };
404 407
405 #undef TRACE 408 #undef TRACE
406 } // namespace wasm 409 } // namespace wasm
407 } // namespace internal 410 } // namespace internal
408 } // namespace v8 411 } // namespace v8
409 412
410 #endif // V8_WASM_DECODER_H_ 413 #endif // V8_WASM_DECODER_H_
OLDNEW
« no previous file with comments | « src/wasm/ast-decoder.cc ('k') | test/unittests/wasm/decoder-unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698