| 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); }
|
|
|