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

Unified Diff: src/wasm/decoder.h

Issue 1746063003: [wasm] Add support for 64-bit LEB encodings. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 10 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | test/unittests/wasm/decoder-unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/wasm/decoder.h
diff --git a/src/wasm/decoder.h b/src/wasm/decoder.h
index 2dfdd02aed912387d75b4c31cef0656a26ca5263..4b35685bd89c7027ed39ee4d6657a5441ed84c4d 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,46 @@ 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));
+ 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
« no previous file with comments | « no previous file | test/unittests/wasm/decoder-unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698