blob: 685f5d0bbf5ec5d7bfa53df55f21bb35a7a457b7 [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// 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
3// found in the LICENSE file.
4
5#ifndef V8_WASM_DECODER_H_
6#define V8_WASM_DECODER_H_
7
Ben Murdochc5610432016-08-08 18:44:38 +01008#include "src/base/compiler-specific.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009#include "src/base/smart-pointers.h"
10#include "src/flags.h"
11#include "src/signature.h"
Ben Murdochc5610432016-08-08 18:44:38 +010012#include "src/utils.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013#include "src/wasm/wasm-result.h"
14#include "src/zone-containers.h"
15
16namespace v8 {
17namespace internal {
18namespace wasm {
19
20#if DEBUG
21#define TRACE(...) \
22 do { \
23 if (FLAG_trace_wasm_decoder) PrintF(__VA_ARGS__); \
24 } while (false)
25#else
26#define TRACE(...)
27#endif
28
Ben Murdoch097c5b22016-05-18 11:27:45 +010029#if !(V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_ARM)
30#define UNALIGNED_ACCESS_OK 1
31#else
32#define UNALIGNED_ACCESS_OK 0
33#endif
34
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000035// A helper utility to decode bytes, integers, fields, varints, etc, from
36// a buffer of bytes.
37class Decoder {
38 public:
39 Decoder(const byte* start, const byte* end)
40 : start_(start),
41 pc_(start),
42 limit_(end),
Ben Murdoch097c5b22016-05-18 11:27:45 +010043 end_(end),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000044 error_pc_(nullptr),
45 error_pt_(nullptr) {}
46
47 virtual ~Decoder() {}
48
Ben Murdoch097c5b22016-05-18 11:27:45 +010049 inline bool check(const byte* base, int offset, int length, const char* msg) {
50 DCHECK_GE(base, start_);
51 if ((base + offset + length) > limit_) {
Ben Murdochc5610432016-08-08 18:44:38 +010052 error(base, base + offset, "%s", msg);
Ben Murdoch097c5b22016-05-18 11:27:45 +010053 return false;
54 }
55 return true;
56 }
57
58 // 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 const char* msg = "expected 1 byte") {
61 return check(base, offset, 1, msg) ? base[offset] : 0;
62 }
63
64 // Reads 16-bit word, reporting an error if out of bounds.
65 inline uint16_t checked_read_u16(const byte* base, int offset,
66 const char* msg = "expected 2 bytes") {
67 return check(base, offset, 2, msg) ? read_u16(base + offset) : 0;
68 }
69
70 // Reads 32-bit word, reporting an error if out of bounds.
71 inline uint32_t checked_read_u32(const byte* base, int offset,
72 const char* msg = "expected 4 bytes") {
73 return check(base, offset, 4, msg) ? read_u32(base + offset) : 0;
74 }
75
76 // Reads 64-bit word, reporting an error if out of bounds.
77 inline uint64_t checked_read_u64(const byte* base, int offset,
78 const char* msg = "expected 8 bytes") {
79 return check(base, offset, 8, msg) ? read_u64(base + offset) : 0;
80 }
81
Ben Murdochda12d292016-06-02 14:46:10 +010082 // Reads a variable-length unsigned integer (little endian).
Ben Murdoch097c5b22016-05-18 11:27:45 +010083 uint32_t checked_read_u32v(const byte* base, int offset, int* length,
Ben Murdochda12d292016-06-02 14:46:10 +010084 const char* msg = "expected LEB32") {
85 return checked_read_leb<uint32_t, false>(base, offset, length, msg);
86 }
Ben Murdoch097c5b22016-05-18 11:27:45 +010087
Ben Murdochda12d292016-06-02 14:46:10 +010088 // Reads a variable-length signed integer (little endian).
89 int32_t checked_read_i32v(const byte* base, int offset, int* length,
90 const char* msg = "expected SLEB32") {
91 uint32_t result =
92 checked_read_leb<uint32_t, true>(base, offset, length, msg);
93 if (*length == 5) return bit_cast<int32_t>(result);
94 if (*length > 0) {
95 int shift = 32 - 7 * *length;
96 // Perform sign extension.
97 return bit_cast<int32_t>(result << shift) >> shift;
Ben Murdoch097c5b22016-05-18 11:27:45 +010098 }
Ben Murdochda12d292016-06-02 14:46:10 +010099 return 0;
100 }
101
102 // Reads a variable-length unsigned integer (little endian).
103 uint64_t checked_read_u64v(const byte* base, int offset, int* length,
104 const char* msg = "expected LEB64") {
105 return checked_read_leb<uint64_t, false>(base, offset, length, msg);
106 }
107
108 // Reads a variable-length signed integer (little endian).
109 int64_t checked_read_i64v(const byte* base, int offset, int* length,
110 const char* msg = "expected SLEB64") {
111 uint64_t result =
112 checked_read_leb<uint64_t, true>(base, offset, length, msg);
113 if (*length == 10) return bit_cast<int64_t>(result);
114 if (*length > 0) {
115 int shift = 64 - 7 * *length;
116 // Perform sign extension.
117 return bit_cast<int64_t>(result << shift) >> shift;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100118 }
Ben Murdochda12d292016-06-02 14:46:10 +0100119 return 0;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100120 }
121
122 // Reads a single 16-bit unsigned integer (little endian).
123 inline uint16_t read_u16(const byte* ptr) {
124 DCHECK(ptr >= start_ && (ptr + 2) <= end_);
125#if V8_TARGET_LITTLE_ENDIAN && UNALIGNED_ACCESS_OK
126 return *reinterpret_cast<const uint16_t*>(ptr);
127#else
128 uint16_t b0 = ptr[0];
129 uint16_t b1 = ptr[1];
130 return (b1 << 8) | b0;
131#endif
132 }
133
134 // Reads a single 32-bit unsigned integer (little endian).
135 inline uint32_t read_u32(const byte* ptr) {
136 DCHECK(ptr >= start_ && (ptr + 4) <= end_);
137#if V8_TARGET_LITTLE_ENDIAN && UNALIGNED_ACCESS_OK
138 return *reinterpret_cast<const uint32_t*>(ptr);
139#else
140 uint32_t b0 = ptr[0];
141 uint32_t b1 = ptr[1];
142 uint32_t b2 = ptr[2];
143 uint32_t b3 = ptr[3];
144 return (b3 << 24) | (b2 << 16) | (b1 << 8) | b0;
145#endif
146 }
147
148 // Reads a single 64-bit unsigned integer (little endian).
149 inline uint64_t read_u64(const byte* ptr) {
150 DCHECK(ptr >= start_ && (ptr + 8) <= end_);
151#if V8_TARGET_LITTLE_ENDIAN && UNALIGNED_ACCESS_OK
152 return *reinterpret_cast<const uint64_t*>(ptr);
153#else
154 uint32_t b0 = ptr[0];
155 uint32_t b1 = ptr[1];
156 uint32_t b2 = ptr[2];
157 uint32_t b3 = ptr[3];
158 uint32_t low = (b3 << 24) | (b2 << 16) | (b1 << 8) | b0;
159 uint32_t b4 = ptr[4];
160 uint32_t b5 = ptr[5];
161 uint32_t b6 = ptr[6];
162 uint32_t b7 = ptr[7];
163 uint64_t high = (b7 << 24) | (b6 << 16) | (b5 << 8) | b4;
164 return (high << 32) | low;
165#endif
166 }
167
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000168 // Reads a 8-bit unsigned integer (byte) and advances {pc_}.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100169 uint8_t consume_u8(const char* name = nullptr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000170 TRACE(" +%d %-20s: ", static_cast<int>(pc_ - start_),
171 name ? name : "uint8_t");
172 if (checkAvailable(1)) {
173 byte val = *(pc_++);
174 TRACE("%02x = %d\n", val, val);
175 return val;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000176 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100177 return traceOffEnd<uint8_t>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000178 }
179
180 // Reads a 16-bit unsigned integer (little endian) and advances {pc_}.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100181 uint16_t consume_u16(const char* name = nullptr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000182 TRACE(" +%d %-20s: ", static_cast<int>(pc_ - start_),
183 name ? name : "uint16_t");
184 if (checkAvailable(2)) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100185 uint16_t val = read_u16(pc_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000186 TRACE("%02x %02x = %d\n", pc_[0], pc_[1], val);
187 pc_ += 2;
188 return val;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000189 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100190 return traceOffEnd<uint16_t>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000191 }
192
193 // Reads a single 32-bit unsigned integer (little endian) and advances {pc_}.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100194 uint32_t consume_u32(const char* name = nullptr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000195 TRACE(" +%d %-20s: ", static_cast<int>(pc_ - start_),
196 name ? name : "uint32_t");
197 if (checkAvailable(4)) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100198 uint32_t val = read_u32(pc_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000199 TRACE("%02x %02x %02x %02x = %u\n", pc_[0], pc_[1], pc_[2], pc_[3], val);
200 pc_ += 4;
201 return val;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000202 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100203 return traceOffEnd<uint32_t>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000204 }
205
206 // Reads a LEB128 variable-length 32-bit integer and advances {pc_}.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100207 uint32_t consume_u32v(int* length, const char* name = nullptr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000208 TRACE(" +%d %-20s: ", static_cast<int>(pc_ - start_),
209 name ? name : "varint");
210
Ben Murdoch097c5b22016-05-18 11:27:45 +0100211 if (checkAvailable(1)) {
212 const byte* pos = pc_;
213 const byte* end = pc_ + 5;
214 if (end > limit_) end = limit_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000215
Ben Murdoch097c5b22016-05-18 11:27:45 +0100216 uint32_t result = 0;
217 int shift = 0;
218 byte b = 0;
219 while (pc_ < end) {
220 b = *pc_++;
221 TRACE("%02x ", b);
222 result = result | ((b & 0x7F) << shift);
223 if ((b & 0x80) == 0) break;
224 shift += 7;
225 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000226
Ben Murdoch097c5b22016-05-18 11:27:45 +0100227 *length = static_cast<int>(pc_ - pos);
228 if (pc_ == end && (b & 0x80)) {
229 error(pc_ - 1, "varint too large");
Ben Murdochda12d292016-06-02 14:46:10 +0100230 } else if (*length == 0) {
231 error(pc_, "varint of length 0");
Ben Murdoch097c5b22016-05-18 11:27:45 +0100232 } else {
233 TRACE("= %u\n", result);
234 }
235 return result;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000236 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100237 return traceOffEnd<uint32_t>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000238 }
239
Ben Murdochda12d292016-06-02 14:46:10 +0100240 // Consume {size} bytes and send them to the bit bucket, advancing {pc_}.
241 void consume_bytes(int size) {
242 if (checkAvailable(size)) {
243 pc_ += size;
244 } else {
245 pc_ = limit_;
246 }
247 }
248
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000249 // Check that at least {size} bytes exist between {pc_} and {limit_}.
250 bool checkAvailable(int size) {
Ben Murdochda12d292016-06-02 14:46:10 +0100251 intptr_t pc_overflow_value = std::numeric_limits<intptr_t>::max() - size;
252 if (size < 0 || (intptr_t)pc_ > pc_overflow_value) {
253 error(pc_, nullptr, "reading %d bytes would underflow/overflow", size);
254 return false;
255 } else if (pc_ < start_ || limit_ < (pc_ + size)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000256 error(pc_, nullptr, "expected %d bytes, fell off end", size);
257 return false;
258 } else {
259 return true;
260 }
261 }
262
Ben Murdochc5610432016-08-08 18:44:38 +0100263 void error(const char* msg) { error(pc_, nullptr, "%s", msg); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000264
Ben Murdochc5610432016-08-08 18:44:38 +0100265 void error(const byte* pc, const char* msg) { error(pc, nullptr, "%s", msg); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000266
267 // Sets internal error state.
Ben Murdochc5610432016-08-08 18:44:38 +0100268 void PRINTF_FORMAT(4, 5)
269 error(const byte* pc, const byte* pt, const char* format, ...) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000270 if (ok()) {
271#if DEBUG
272 if (FLAG_wasm_break_on_decoder_error) {
273 base::OS::DebugBreak();
274 }
275#endif
276 const int kMaxErrorMsg = 256;
277 char* buffer = new char[kMaxErrorMsg];
278 va_list arguments;
279 va_start(arguments, format);
280 base::OS::VSNPrintF(buffer, kMaxErrorMsg - 1, format, arguments);
281 va_end(arguments);
282 error_msg_.Reset(buffer);
283 error_pc_ = pc;
284 error_pt_ = pt;
285 onFirstError();
286 }
287 }
288
289 // Behavior triggered on first error, overridden in subclasses.
290 virtual void onFirstError() {}
291
292 // Debugging helper to print bytes up to the end.
293 template <typename T>
294 T traceOffEnd() {
295 T t = 0;
296 for (const byte* ptr = pc_; ptr < limit_; ptr++) {
297 TRACE("%02x ", *ptr);
298 }
299 TRACE("<end>\n");
300 pc_ = limit_;
301 return t;
302 }
303
304 // Converts the given value to a {Result}, copying the error if necessary.
305 template <typename T>
306 Result<T> toResult(T val) {
307 Result<T> result;
308 if (error_pc_) {
Ben Murdochda12d292016-06-02 14:46:10 +0100309 TRACE("Result error: %s\n", error_msg_.get());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000310 result.error_code = kError;
311 result.start = start_;
312 result.error_pc = error_pc_;
313 result.error_pt = error_pt_;
Ben Murdochda12d292016-06-02 14:46:10 +0100314 // transfer ownership of the error to the result.
315 result.error_msg.Reset(error_msg_.Detach());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000316 } else {
317 result.error_code = kSuccess;
318 }
319 result.val = val;
320 return result;
321 }
322
323 // Resets the boundaries of this decoder.
324 void Reset(const byte* start, const byte* end) {
325 start_ = start;
326 pc_ = start;
327 limit_ = end;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100328 end_ = end;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000329 error_pc_ = nullptr;
330 error_pt_ = nullptr;
331 error_msg_.Reset(nullptr);
332 }
333
334 bool ok() const { return error_pc_ == nullptr; }
Ben Murdochda12d292016-06-02 14:46:10 +0100335 bool failed() const { return !error_msg_.is_empty(); }
336 bool more() const { return pc_ < limit_; }
337
338 const byte* start() { return start_; }
339 const byte* pc() { return pc_; }
340 uint32_t pc_offset() { return static_cast<uint32_t>(pc_ - start_); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000341
342 protected:
343 const byte* start_;
344 const byte* pc_;
345 const byte* limit_;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100346 const byte* end_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000347 const byte* error_pc_;
348 const byte* error_pt_;
349 base::SmartArrayPointer<char> error_msg_;
Ben Murdochda12d292016-06-02 14:46:10 +0100350
351 private:
352 template <typename IntType, bool is_signed>
353 IntType checked_read_leb(const byte* base, int offset, int* length,
354 const char* msg) {
355 if (!check(base, offset, 1, msg)) {
356 *length = 0;
357 return 0;
358 }
359
360 const int kMaxLength = (sizeof(IntType) * 8 + 6) / 7;
361 const byte* ptr = base + offset;
362 const byte* end = ptr + kMaxLength;
363 if (end > limit_) end = limit_;
364 int shift = 0;
365 byte b = 0;
366 IntType result = 0;
367 while (ptr < end) {
368 b = *ptr++;
369 result = result | (static_cast<IntType>(b & 0x7F) << shift);
370 if ((b & 0x80) == 0) break;
371 shift += 7;
372 }
373 DCHECK_LE(ptr - (base + offset), kMaxLength);
374 *length = static_cast<int>(ptr - (base + offset));
375 if (ptr == end) {
376 // Check there are no bits set beyond the bitwidth of {IntType}.
377 const int kExtraBits = (1 + kMaxLength * 7) - (sizeof(IntType) * 8);
378 const byte kExtraBitsMask =
379 static_cast<byte>((0xFF << (8 - kExtraBits)) & 0xFF);
380 int extra_bits_value;
381 if (is_signed) {
382 // A signed-LEB128 must sign-extend the final byte, excluding its
383 // most-signifcant bit. e.g. for a 32-bit LEB128:
384 // kExtraBits = 4
385 // kExtraBitsMask = 0xf0
386 // If b is 0x0f, the value is negative, so extra_bits_value is 0x70.
387 // If b is 0x03, the value is positive, so extra_bits_value is 0x00.
388 extra_bits_value = (static_cast<int8_t>(b << kExtraBits) >> 8) &
389 kExtraBitsMask & ~0x80;
390 } else {
391 extra_bits_value = 0;
392 }
393 if (*length == kMaxLength && (b & kExtraBitsMask) != extra_bits_value) {
394 error(base, ptr, "extra bits in varint");
395 return 0;
396 }
397 if ((b & 0x80) != 0) {
Ben Murdochc5610432016-08-08 18:44:38 +0100398 error(base, ptr, "%s", msg);
Ben Murdochda12d292016-06-02 14:46:10 +0100399 return 0;
400 }
401 }
402 return result;
403 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000404};
405
406#undef TRACE
407} // namespace wasm
408} // namespace internal
409} // namespace v8
410
411#endif // V8_WASM_DECODER_H_