| Index: src/wasm/decoder.h
|
| diff --git a/src/wasm/decoder.h b/src/wasm/decoder.h
|
| index 2dfdd02aed912387d75b4c31cef0656a26ca5263..ef7f85f166b09595c8ee6a2b5ff83646c10ed4e4 100644
|
| --- a/src/wasm/decoder.h
|
| +++ b/src/wasm/decoder.h
|
| @@ -77,53 +77,44 @@ class Decoder {
|
| return check(base, offset, 8, msg) ? read_u64(base + offset) : 0;
|
| }
|
|
|
| + // Reads a variable-length unsigned integer (little endian).
|
| 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) {
|
| - if (*length == kMaxDiff && (b & 0xF0) != 0) {
|
| - error(base, ptr, "extra bits in LEB128");
|
| - return 0;
|
| - }
|
| - if ((b & 0x80) != 0) {
|
| - error(base, ptr, msg);
|
| - return 0;
|
| - }
|
| - }
|
| - return result;
|
| + const char* msg = "expected LEB32") {
|
| + return checked_read_leb<uint32_t>(base, offset, length, msg);
|
| }
|
|
|
| // Reads a variable-length signed integer (little endian).
|
| int32_t checked_read_i32v(const byte* base, int offset, int* length,
|
| - const char* msg = "expected SLEB128") {
|
| + const char* msg = "expected SLEB32") {
|
| uint32_t result = checked_read_u32v(base, offset, length, msg);
|
| if (*length == 5) return bit_cast<int32_t>(result);
|
| if (*length > 0) {
|
| int shift = 32 - 7 * *length;
|
| + // Perform sign extension.
|
| return bit_cast<int32_t>(result << shift) >> shift;
|
| }
|
| return 0;
|
| }
|
|
|
| + // Reads a variable-length unsigned integer (little endian).
|
| + uint64_t checked_read_u64v(const byte* base, int offset, int* length,
|
| + const char* msg = "expected LEB64") {
|
| + return checked_read_leb<uint64_t>(base, offset, length, msg);
|
| + }
|
| +
|
| + // Reads a variable-length signed integer (little endian).
|
| + int64_t checked_read_i64v(const byte* base, int offset, int* length,
|
| + const char* msg = "expected SLEB64") {
|
| + uint64_t result = checked_read_u64v(base, offset, length, msg);
|
| + if (*length == 10) return bit_cast<int64_t>(result);
|
| + if (*length > 0) {
|
| + int shift = 64 - 7 * *length;
|
| + // Perform sign extension.
|
| + return bit_cast<int64_t>(result << shift) >> shift;
|
| + }
|
| + return 0;
|
| + }
|
| +
|
| // Reads a single 16-bit unsigned integer (little endian).
|
| inline uint16_t read_u16(const byte* ptr) {
|
| DCHECK(ptr >= start_ && (ptr + 2) <= end_);
|
| @@ -333,6 +324,47 @@ class Decoder {
|
| const byte* error_pc_;
|
| const byte* error_pt_;
|
| base::SmartArrayPointer<char> error_msg_;
|
| +
|
| + private:
|
| + template <typename IntType>
|
| + IntType checked_read_leb(const byte* base, int offset, int* length,
|
| + const char* msg) {
|
| + if (!check(base, offset, 1, msg)) {
|
| + *length = 0;
|
| + return 0;
|
| + }
|
| +
|
| + const int kMaxLength = (sizeof(IntType) * 8 + 6) / 7;
|
| + const byte* ptr = base + offset;
|
| + const byte* end = ptr + kMaxLength;
|
| + if (end > limit_) end = limit_;
|
| + int shift = 0;
|
| + byte b = 0;
|
| + IntType result = 0;
|
| + while (ptr < end) {
|
| + b = *ptr++;
|
| + result = result | (static_cast<IntType>(b & 0x7F) << shift);
|
| + if ((b & 0x80) == 0) break;
|
| + shift += 7;
|
| + }
|
| + DCHECK_LE(ptr - (base + offset), kMaxLength);
|
| + *length = static_cast<int>(ptr - (base + offset));
|
| + if (ptr == end) {
|
| + // Check there are no bits set beyond the bitwidth of {IntType}.
|
| + const int kExtraBits = (1 + kMaxLength * 7) - (sizeof(IntType) * 8);
|
| + const byte kExtraBitsMask =
|
| + static_cast<byte>((0xFF << (8 - kExtraBits)) & 0xFF);
|
| + if (*length == kMaxLength && (b & kExtraBitsMask) != 0) {
|
| + error(base, ptr, "extra bits in varint");
|
| + return 0;
|
| + }
|
| + if ((b & 0x80) != 0) {
|
| + error(base, ptr, msg);
|
| + return 0;
|
| + }
|
| + }
|
| + return result;
|
| + }
|
| };
|
|
|
| #undef TRACE
|
|
|