Index: src/wasm/decoder.h |
diff --git a/src/wasm/decoder.h b/src/wasm/decoder.h |
index 433e80a186a7f616d5cee2376a0af0e269a7b3b6..0e88eda022de439228b6f862098dff55376ae954 100644 |
--- a/src/wasm/decoder.h |
+++ b/src/wasm/decoder.h |
@@ -44,6 +44,68 @@ class Decoder { |
virtual ~Decoder() {} |
+ inline bool check(const byte* base, int offset, int length, const char* msg) { |
+ DCHECK_GE(base, start_); |
+ if ((base + offset + length) > limit_) { |
+ error(base, base + offset, msg); |
+ return false; |
+ } |
+ return true; |
+ } |
+ |
+ // Reads a single 8-bit byte, reporting an error if out of bounds. |
+ inline uint8_t checked_read_u8(const byte* base, int offset, |
+ const char* msg = "expected 1 byte") { |
+ return check(base, offset, 1, msg) ? base[offset] : 0; |
+ } |
+ |
+ // Reads 16-bit word, reporting an error if out of bounds. |
+ inline uint16_t checked_read_u16(const byte* base, int offset, |
+ const char* msg = "expected 2 bytes") { |
+ return check(base, offset, 2, msg) ? read_u16(base + offset) : 0; |
+ } |
+ |
+ // Reads 32-bit word, reporting an error if out of bounds. |
+ inline uint32_t checked_read_u32(const byte* base, int offset, |
+ const char* msg = "expected 4 bytes") { |
+ return check(base, offset, 4, msg) ? read_u32(base + offset) : 0; |
+ } |
+ |
+ // Reads 64-bit word, reporting an error if out of bounds. |
+ inline uint64_t checked_read_u64(const byte* base, int offset, |
+ const char* msg = "expected 8 bytes") { |
+ return check(base, offset, 8, msg) ? read_u64(base + offset) : 0; |
+ } |
+ |
+ uint32_t checked_read_u32v(const byte* base, int offset, int* length, |
+ const char* msg = "expected LEB128") { |
+ if (!check(base, offset, 1, msg)) { |
+ *length = 0; |
+ return 0; |
+ } |
+ |
+ const ptrdiff_t kMaxDiff = 5; // maximum 5 bytes. |
+ const byte* ptr = base + offset; |
+ const byte* end = ptr + kMaxDiff; |
+ if (end > limit_) end = limit_; |
+ int shift = 0; |
+ byte b = 0; |
+ uint32_t result = 0; |
+ while (ptr < end) { |
+ b = *ptr++; |
+ result = result | ((b & 0x7F) << shift); |
+ if ((b & 0x80) == 0) break; |
+ shift += 7; |
+ } |
+ DCHECK_LE(ptr - (base + offset), kMaxDiff); |
+ *length = static_cast<int>(ptr - (base + offset)); |
+ if (ptr == end && (b & 0x80)) { |
+ error(base, ptr, msg); |
+ return 0; |
+ } |
+ return result; |
+ } |
+ |
// Reads a single 16-bit unsigned integer (little endian). |
inline uint16_t read_u16(const byte* ptr) { |
DCHECK(ptr >= start_ && (ptr + 2) <= end_); |
@@ -170,6 +232,12 @@ class Decoder { |
} |
} |
+ bool RangeOk(const byte* pc, int length) { |
+ if (pc < start_ || pc_ >= limit_) return false; |
+ if ((pc + length) >= limit_) return false; |
+ return true; |
+ } |
+ |
void error(const char* msg) { error(pc_, nullptr, msg); } |
void error(const byte* pc, const char* msg) { error(pc, nullptr, msg); } |