| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef V8_WASM_DECODER_H_ | 5 #ifndef V8_WASM_DECODER_H_ |
| 6 #define V8_WASM_DECODER_H_ | 6 #define V8_WASM_DECODER_H_ |
| 7 | 7 |
| 8 #include <memory> | 8 #include <memory> |
| 9 | 9 |
| 10 #include "src/base/compiler-specific.h" | 10 #include "src/base/compiler-specific.h" |
| (...skipping 16 matching lines...) Expand all Loading... |
| 27 #define TRACE(...) | 27 #define TRACE(...) |
| 28 #endif | 28 #endif |
| 29 | 29 |
| 30 // A helper utility to decode bytes, integers, fields, varints, etc, from | 30 // A helper utility to decode bytes, integers, fields, varints, etc, from |
| 31 // a buffer of bytes. | 31 // a buffer of bytes. |
| 32 class Decoder { | 32 class Decoder { |
| 33 public: | 33 public: |
| 34 Decoder(const byte* start, const byte* end) | 34 Decoder(const byte* start, const byte* end) |
| 35 : start_(start), | 35 : start_(start), |
| 36 pc_(start), | 36 pc_(start), |
| 37 limit_(end), | |
| 38 end_(end), | 37 end_(end), |
| 39 error_pc_(nullptr), | 38 error_pc_(nullptr), |
| 40 error_pt_(nullptr) {} | 39 error_pt_(nullptr) {} |
| 41 | 40 |
| 42 virtual ~Decoder() {} | 41 virtual ~Decoder() {} |
| 43 | 42 |
| 44 inline bool check(const byte* base, unsigned offset, unsigned length, | 43 inline bool check(const byte* base, unsigned offset, unsigned length, |
| 45 const char* msg) { | 44 const char* msg) { |
| 46 DCHECK_GE(base, start_); | 45 DCHECK_GE(base, start_); |
| 47 if ((base + offset + length) > limit_) { | 46 if ((base + offset + length) > end_) { |
| 48 error(base, base + offset, "%s", msg); | 47 error(base, base + offset, "%s", msg); |
| 49 return false; | 48 return false; |
| 50 } | 49 } |
| 51 return true; | 50 return true; |
| 52 } | 51 } |
| 53 | 52 |
| 54 // Reads a single 8-bit byte, reporting an error if out of bounds. | 53 // Reads a single 8-bit byte, reporting an error if out of bounds. |
| 55 inline uint8_t checked_read_u8(const byte* base, unsigned offset, | 54 inline uint8_t checked_read_u8(const byte* base, unsigned offset, |
| 56 const char* msg = "expected 1 byte") { | 55 const char* msg = "expected 1 byte") { |
| 57 return check(base, offset, 1, msg) ? base[offset] : 0; | 56 return check(base, offset, 1, msg) ? base[offset] : 0; |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 183 return consume_leb<int32_t, true>(name); | 182 return consume_leb<int32_t, true>(name); |
| 184 } | 183 } |
| 185 | 184 |
| 186 // Consume {size} bytes and send them to the bit bucket, advancing {pc_}. | 185 // Consume {size} bytes and send them to the bit bucket, advancing {pc_}. |
| 187 void consume_bytes(uint32_t size, const char* name = "skip") { | 186 void consume_bytes(uint32_t size, const char* name = "skip") { |
| 188 TRACE(" +%d %-20s: %d bytes\n", static_cast<int>(pc_ - start_), name, | 187 TRACE(" +%d %-20s: %d bytes\n", static_cast<int>(pc_ - start_), name, |
| 189 size); | 188 size); |
| 190 if (checkAvailable(size)) { | 189 if (checkAvailable(size)) { |
| 191 pc_ += size; | 190 pc_ += size; |
| 192 } else { | 191 } else { |
| 193 pc_ = limit_; | 192 pc_ = end_; |
| 194 } | 193 } |
| 195 } | 194 } |
| 196 | 195 |
| 197 // Check that at least {size} bytes exist between {pc_} and {limit_}. | 196 // Check that at least {size} bytes exist between {pc_} and {end_}. |
| 198 bool checkAvailable(int size) { | 197 bool checkAvailable(int size) { |
| 199 intptr_t pc_overflow_value = std::numeric_limits<intptr_t>::max() - size; | 198 intptr_t pc_overflow_value = std::numeric_limits<intptr_t>::max() - size; |
| 200 if (size < 0 || (intptr_t)pc_ > pc_overflow_value) { | 199 if (size < 0 || (intptr_t)pc_ > pc_overflow_value) { |
| 201 error(pc_, nullptr, "reading %d bytes would underflow/overflow", size); | 200 error(pc_, nullptr, "reading %d bytes would underflow/overflow", size); |
| 202 return false; | 201 return false; |
| 203 } else if (pc_ < start_ || limit_ < (pc_ + size)) { | 202 } else if (pc_ < start_ || end_ < (pc_ + size)) { |
| 204 error(pc_, nullptr, "expected %d bytes, fell off end", size); | 203 error(pc_, nullptr, "expected %d bytes, fell off end", size); |
| 205 return false; | 204 return false; |
| 206 } else { | 205 } else { |
| 207 return true; | 206 return true; |
| 208 } | 207 } |
| 209 } | 208 } |
| 210 | 209 |
| 211 void error(const char* msg) { error(pc_, nullptr, "%s", msg); } | 210 void error(const char* msg) { error(pc_, nullptr, "%s", msg); } |
| 212 | 211 |
| 213 void error(const byte* pc, const char* msg) { error(pc, nullptr, "%s", msg); } | 212 void error(const byte* pc, const char* msg) { error(pc, nullptr, "%s", msg); } |
| (...skipping 20 matching lines...) Expand all Loading... |
| 234 } | 233 } |
| 235 } | 234 } |
| 236 | 235 |
| 237 // Behavior triggered on first error, overridden in subclasses. | 236 // Behavior triggered on first error, overridden in subclasses. |
| 238 virtual void onFirstError() {} | 237 virtual void onFirstError() {} |
| 239 | 238 |
| 240 // Debugging helper to print bytes up to the end. | 239 // Debugging helper to print bytes up to the end. |
| 241 template <typename T> | 240 template <typename T> |
| 242 T traceOffEnd() { | 241 T traceOffEnd() { |
| 243 T t = 0; | 242 T t = 0; |
| 244 for (const byte* ptr = pc_; ptr < limit_; ptr++) { | 243 for (const byte* ptr = pc_; ptr < end_; ptr++) { |
| 245 TRACE("%02x ", *ptr); | 244 TRACE("%02x ", *ptr); |
| 246 } | 245 } |
| 247 TRACE("<end>\n"); | 246 TRACE("<end>\n"); |
| 248 pc_ = limit_; | 247 pc_ = end_; |
| 249 return t; | 248 return t; |
| 250 } | 249 } |
| 251 | 250 |
| 252 // Converts the given value to a {Result}, copying the error if necessary. | 251 // Converts the given value to a {Result}, copying the error if necessary. |
| 253 template <typename T> | 252 template <typename T> |
| 254 Result<T> toResult(T val) { | 253 Result<T> toResult(T val) { |
| 255 Result<T> result; | 254 Result<T> result; |
| 256 if (failed()) { | 255 if (failed()) { |
| 257 TRACE("Result error: %s\n", error_msg_.get()); | 256 TRACE("Result error: %s\n", error_msg_.get()); |
| 258 result.error_code = kError; | 257 result.error_code = kError; |
| 259 result.start = start_; | 258 result.start = start_; |
| 260 result.error_pc = error_pc_; | 259 result.error_pc = error_pc_; |
| 261 result.error_pt = error_pt_; | 260 result.error_pt = error_pt_; |
| 262 // transfer ownership of the error to the result. | 261 // transfer ownership of the error to the result. |
| 263 result.error_msg.reset(error_msg_.release()); | 262 result.error_msg.reset(error_msg_.release()); |
| 264 } else { | 263 } else { |
| 265 result.error_code = kSuccess; | 264 result.error_code = kSuccess; |
| 266 } | 265 } |
| 267 result.val = std::move(val); | 266 result.val = std::move(val); |
| 268 return result; | 267 return result; |
| 269 } | 268 } |
| 270 | 269 |
| 271 // Resets the boundaries of this decoder. | 270 // Resets the boundaries of this decoder. |
| 272 void Reset(const byte* start, const byte* end) { | 271 void Reset(const byte* start, const byte* end) { |
| 273 start_ = start; | 272 start_ = start; |
| 274 pc_ = start; | 273 pc_ = start; |
| 275 limit_ = end; | |
| 276 end_ = end; | 274 end_ = end; |
| 277 error_pc_ = nullptr; | 275 error_pc_ = nullptr; |
| 278 error_pt_ = nullptr; | 276 error_pt_ = nullptr; |
| 279 error_msg_.reset(); | 277 error_msg_.reset(); |
| 280 } | 278 } |
| 281 | 279 |
| 282 bool ok() const { return error_msg_ == nullptr; } | 280 bool ok() const { return error_msg_ == nullptr; } |
| 283 bool failed() const { return !ok(); } | 281 bool failed() const { return !ok(); } |
| 284 bool more() const { return pc_ < limit_; } | 282 bool more() const { return pc_ < end_; } |
| 285 | 283 |
| 286 const byte* start() { return start_; } | 284 const byte* start() { return start_; } |
| 287 const byte* pc() { return pc_; } | 285 const byte* pc() { return pc_; } |
| 288 uint32_t pc_offset() { return static_cast<uint32_t>(pc_ - start_); } | 286 uint32_t pc_offset() { return static_cast<uint32_t>(pc_ - start_); } |
| 289 | 287 |
| 290 protected: | 288 protected: |
| 291 const byte* start_; | 289 const byte* start_; |
| 292 const byte* pc_; | 290 const byte* pc_; |
| 293 const byte* limit_; | |
| 294 const byte* end_; | 291 const byte* end_; |
| 295 const byte* error_pc_; | 292 const byte* error_pc_; |
| 296 const byte* error_pt_; | 293 const byte* error_pt_; |
| 297 std::unique_ptr<char[]> error_msg_; | 294 std::unique_ptr<char[]> error_msg_; |
| 298 | 295 |
| 299 private: | 296 private: |
| 300 template <typename IntType, bool is_signed> | 297 template <typename IntType, bool is_signed> |
| 301 IntType checked_read_leb(const byte* base, unsigned offset, unsigned* length, | 298 IntType checked_read_leb(const byte* base, unsigned offset, unsigned* length, |
| 302 const char* msg) { | 299 const char* msg) { |
| 303 if (!check(base, offset, 1, msg)) { | 300 if (!check(base, offset, 1, msg)) { |
| 304 *length = 0; | 301 *length = 0; |
| 305 return 0; | 302 return 0; |
| 306 } | 303 } |
| 307 | 304 |
| 308 const int kMaxLength = (sizeof(IntType) * 8 + 6) / 7; | 305 const int kMaxLength = (sizeof(IntType) * 8 + 6) / 7; |
| 309 const byte* ptr = base + offset; | 306 const byte* ptr = base + offset; |
| 310 const byte* end = ptr + kMaxLength; | 307 const byte* end = ptr + kMaxLength; |
| 311 if (end > limit_) end = limit_; | 308 if (end > end_) end = end_; |
| 312 int shift = 0; | 309 int shift = 0; |
| 313 byte b = 0; | 310 byte b = 0; |
| 314 IntType result = 0; | 311 IntType result = 0; |
| 315 while (ptr < end) { | 312 while (ptr < end) { |
| 316 b = *ptr++; | 313 b = *ptr++; |
| 317 result = result | (static_cast<IntType>(b & 0x7F) << shift); | 314 result = result | (static_cast<IntType>(b & 0x7F) << shift); |
| 318 if ((b & 0x80) == 0) break; | 315 if ((b & 0x80) == 0) break; |
| 319 shift += 7; | 316 shift += 7; |
| 320 } | 317 } |
| 321 DCHECK_LE(ptr - (base + offset), kMaxLength); | 318 DCHECK_LE(ptr - (base + offset), kMaxLength); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 351 } | 348 } |
| 352 | 349 |
| 353 template <typename IntType, bool is_signed> | 350 template <typename IntType, bool is_signed> |
| 354 IntType consume_leb(const char* name = nullptr) { | 351 IntType consume_leb(const char* name = nullptr) { |
| 355 TRACE(" +%d %-20s: ", static_cast<int>(pc_ - start_), | 352 TRACE(" +%d %-20s: ", static_cast<int>(pc_ - start_), |
| 356 name ? name : "varint"); | 353 name ? name : "varint"); |
| 357 if (checkAvailable(1)) { | 354 if (checkAvailable(1)) { |
| 358 const int kMaxLength = (sizeof(IntType) * 8 + 6) / 7; | 355 const int kMaxLength = (sizeof(IntType) * 8 + 6) / 7; |
| 359 const byte* pos = pc_; | 356 const byte* pos = pc_; |
| 360 const byte* end = pc_ + kMaxLength; | 357 const byte* end = pc_ + kMaxLength; |
| 361 if (end > limit_) end = limit_; | 358 if (end > end_) end = end_; |
| 362 | 359 |
| 363 IntType result = 0; | 360 IntType result = 0; |
| 364 int shift = 0; | 361 int shift = 0; |
| 365 byte b = 0; | 362 byte b = 0; |
| 366 while (pc_ < end) { | 363 while (pc_ < end) { |
| 367 b = *pc_++; | 364 b = *pc_++; |
| 368 TRACE("%02x ", b); | 365 TRACE("%02x ", b); |
| 369 result = result | (static_cast<IntType>(b & 0x7F) << shift); | 366 result = result | (static_cast<IntType>(b & 0x7F) << shift); |
| 370 shift += 7; | 367 shift += 7; |
| 371 if ((b & 0x80) == 0) break; | 368 if ((b & 0x80) == 0) break; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 391 return traceOffEnd<uint32_t>(); | 388 return traceOffEnd<uint32_t>(); |
| 392 } | 389 } |
| 393 }; | 390 }; |
| 394 | 391 |
| 395 #undef TRACE | 392 #undef TRACE |
| 396 } // namespace wasm | 393 } // namespace wasm |
| 397 } // namespace internal | 394 } // namespace internal |
| 398 } // namespace v8 | 395 } // namespace v8 |
| 399 | 396 |
| 400 #endif // V8_WASM_DECODER_H_ | 397 #endif // V8_WASM_DECODER_H_ |
| OLD | NEW |