Home | History | Annotate | Download | only in wasm
      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
      3 // found in the LICENSE file.
      4 
      5 #include "src/wasm/module-decoder.h"
      6 #include "src/wasm/function-body-decoder-impl.h"
      7 
      8 #include "src/base/functional.h"
      9 #include "src/base/platform/platform.h"
     10 #include "src/counters.h"
     11 #include "src/flags.h"
     12 #include "src/macro-assembler.h"
     13 #include "src/objects-inl.h"
     14 #include "src/ostreams.h"
     15 #include "src/v8.h"
     16 
     17 #include "src/wasm/decoder.h"
     18 #include "src/wasm/wasm-limits.h"
     19 
     20 namespace v8 {
     21 namespace internal {
     22 namespace wasm {
     23 
     24 #if DEBUG
     25 #define TRACE(...)                                    \
     26   do {                                                \
     27     if (FLAG_trace_wasm_decoder) PrintF(__VA_ARGS__); \
     28   } while (false)
     29 #else
     30 #define TRACE(...)
     31 #endif
     32 
     33 const char* SectionName(WasmSectionCode code) {
     34   switch (code) {
     35     case kUnknownSectionCode:
     36       return "Unknown";
     37     case kTypeSectionCode:
     38       return "Type";
     39     case kImportSectionCode:
     40       return "Import";
     41     case kFunctionSectionCode:
     42       return "Function";
     43     case kTableSectionCode:
     44       return "Table";
     45     case kMemorySectionCode:
     46       return "Memory";
     47     case kGlobalSectionCode:
     48       return "Global";
     49     case kExportSectionCode:
     50       return "Export";
     51     case kStartSectionCode:
     52       return "Start";
     53     case kCodeSectionCode:
     54       return "Code";
     55     case kElementSectionCode:
     56       return "Element";
     57     case kDataSectionCode:
     58       return "Data";
     59     case kNameSectionCode:
     60       return "Name";
     61     default:
     62       return "<unknown>";
     63   }
     64 }
     65 
     66 namespace {
     67 
     68 const char* kNameString = "name";
     69 const size_t kNameStringLength = 4;
     70 
     71 ValueType TypeOf(const WasmModule* module, const WasmInitExpr& expr) {
     72   switch (expr.kind) {
     73     case WasmInitExpr::kNone:
     74       return kWasmStmt;
     75     case WasmInitExpr::kGlobalIndex:
     76       return expr.val.global_index < module->globals.size()
     77                  ? module->globals[expr.val.global_index].type
     78                  : kWasmStmt;
     79     case WasmInitExpr::kI32Const:
     80       return kWasmI32;
     81     case WasmInitExpr::kI64Const:
     82       return kWasmI64;
     83     case WasmInitExpr::kF32Const:
     84       return kWasmF32;
     85     case WasmInitExpr::kF64Const:
     86       return kWasmF64;
     87     default:
     88       UNREACHABLE();
     89       return kWasmStmt;
     90   }
     91 }
     92 
     93 // An iterator over the sections in a WASM binary module.
     94 // Automatically skips all unknown sections.
     95 class WasmSectionIterator {
     96  public:
     97   explicit WasmSectionIterator(Decoder& decoder)
     98       : decoder_(decoder),
     99         section_code_(kUnknownSectionCode),
    100         section_start_(decoder.pc()),
    101         section_end_(decoder.pc()) {
    102     next();
    103   }
    104 
    105   inline bool more() const {
    106     return section_code_ != kUnknownSectionCode && decoder_.more();
    107   }
    108 
    109   inline WasmSectionCode section_code() const { return section_code_; }
    110 
    111   inline const byte* section_start() const { return section_start_; }
    112 
    113   inline uint32_t section_length() const {
    114     return static_cast<uint32_t>(section_end_ - section_start_);
    115   }
    116 
    117   inline const byte* payload_start() const { return payload_start_; }
    118 
    119   inline uint32_t payload_length() const {
    120     return static_cast<uint32_t>(section_end_ - payload_start_);
    121   }
    122 
    123   inline const byte* section_end() const { return section_end_; }
    124 
    125   // Advances to the next section, checking that decoding the current section
    126   // stopped at {section_end_}.
    127   void advance() {
    128     if (decoder_.pc() != section_end_) {
    129       const char* msg = decoder_.pc() < section_end_ ? "shorter" : "longer";
    130       decoder_.error(decoder_.pc(), decoder_.pc(),
    131                      "section was %s than expected size "
    132                      "(%u bytes expected, %zu decoded)",
    133                      msg, section_length(),
    134                      static_cast<size_t>(decoder_.pc() - section_start_));
    135     }
    136     next();
    137   }
    138 
    139  private:
    140   Decoder& decoder_;
    141   WasmSectionCode section_code_;
    142   const byte* section_start_;
    143   const byte* payload_start_;
    144   const byte* section_end_;
    145 
    146   // Reads the section code/name at the current position and sets up
    147   // the internal fields.
    148   void next() {
    149     while (true) {
    150       if (!decoder_.more()) {
    151         section_code_ = kUnknownSectionCode;
    152         return;
    153       }
    154       uint8_t section_code = decoder_.consume_u8("section code");
    155       // Read and check the section size.
    156       uint32_t section_length = decoder_.consume_u32v("section length");
    157       section_start_ = decoder_.pc();
    158       payload_start_ = section_start_;
    159       if (decoder_.checkAvailable(section_length)) {
    160         // Get the limit of the section within the module.
    161         section_end_ = section_start_ + section_length;
    162       } else {
    163         // The section would extend beyond the end of the module.
    164         section_end_ = section_start_;
    165       }
    166 
    167       if (section_code == kUnknownSectionCode) {
    168         // Check for the known "name" section.
    169         uint32_t string_length = decoder_.consume_u32v("section name length");
    170         const byte* section_name_start = decoder_.pc();
    171         decoder_.consume_bytes(string_length, "section name");
    172         if (decoder_.failed() || decoder_.pc() > section_end_) {
    173           TRACE("Section name of length %u couldn't be read\n", string_length);
    174           section_code_ = kUnknownSectionCode;
    175           return;
    176         }
    177         payload_start_ = decoder_.pc();
    178 
    179         TRACE("  +%d  section name        : \"%.*s\"\n",
    180               static_cast<int>(section_name_start - decoder_.start()),
    181               string_length < 20 ? string_length : 20, section_name_start);
    182 
    183         if (string_length == kNameStringLength &&
    184             strncmp(reinterpret_cast<const char*>(section_name_start),
    185                     kNameString, kNameStringLength) == 0) {
    186           section_code = kNameSectionCode;
    187         } else {
    188           section_code = kUnknownSectionCode;
    189         }
    190       } else if (!IsValidSectionCode(section_code)) {
    191         decoder_.error(decoder_.pc(), decoder_.pc(),
    192                        "unknown section code #0x%02x", section_code);
    193         section_code = kUnknownSectionCode;
    194       }
    195       section_code_ = static_cast<WasmSectionCode>(section_code);
    196 
    197       TRACE("Section: %s\n", SectionName(section_code_));
    198       if (section_code_ == kUnknownSectionCode &&
    199           section_end_ > decoder_.pc()) {
    200         // skip to the end of the unknown section.
    201         uint32_t remaining =
    202             static_cast<uint32_t>(section_end_ - decoder_.pc());
    203         decoder_.consume_bytes(remaining, "section payload");
    204         // fall through and continue to the next section.
    205       } else {
    206         return;
    207       }
    208     }
    209   }
    210 };
    211 
    212 // The main logic for decoding the bytes of a module.
    213 class ModuleDecoder : public Decoder {
    214  public:
    215   ModuleDecoder(Zone* zone, const byte* module_start, const byte* module_end,
    216                 ModuleOrigin origin)
    217       : Decoder(module_start, module_end),
    218         module_zone(zone),
    219         origin_(FLAG_assume_asmjs_origin ? kAsmJsOrigin : origin) {
    220     result_.start = start_;
    221     if (end_ < start_) {
    222       error(start_, "end is less than start");
    223       end_ = start_;
    224     }
    225   }
    226 
    227   virtual void onFirstError() {
    228     pc_ = end_;  // On error, terminate section decoding loop.
    229   }
    230 
    231   void DumpModule(const ModuleResult& result) {
    232     std::string path;
    233     if (FLAG_dump_wasm_module_path) {
    234       path = FLAG_dump_wasm_module_path;
    235       if (path.size() &&
    236           !base::OS::isDirectorySeparator(path[path.size() - 1])) {
    237         path += base::OS::DirectorySeparator();
    238       }
    239     }
    240     // File are named `HASH.{ok,failed}.wasm`.
    241     size_t hash = base::hash_range(start_, end_);
    242     char buf[32] = {'\0'};
    243 #if V8_OS_WIN && _MSC_VER < 1900
    244 #define snprintf sprintf_s
    245 #endif
    246     snprintf(buf, sizeof(buf) - 1, "%016zx.%s.wasm", hash,
    247              result.ok() ? "ok" : "failed");
    248     std::string name(buf);
    249     if (FILE* wasm_file = base::OS::FOpen((path + name).c_str(), "wb")) {
    250       fwrite(start_, end_ - start_, 1, wasm_file);
    251       fclose(wasm_file);
    252     }
    253   }
    254 
    255   // Decodes an entire module.
    256   ModuleResult DecodeModule(bool verify_functions = true) {
    257     pc_ = start_;
    258     WasmModule* module = new WasmModule(module_zone);
    259     module->min_mem_pages = 0;
    260     module->max_mem_pages = 0;
    261     module->mem_export = false;
    262     module->origin = origin_;
    263 
    264     const byte* pos = pc_;
    265     uint32_t magic_word = consume_u32("wasm magic");
    266 #define BYTES(x) (x & 0xff), (x >> 8) & 0xff, (x >> 16) & 0xff, (x >> 24) & 0xff
    267     if (magic_word != kWasmMagic) {
    268       error(pos, pos,
    269             "expected magic word %02x %02x %02x %02x, "
    270             "found %02x %02x %02x %02x",
    271             BYTES(kWasmMagic), BYTES(magic_word));
    272     }
    273 
    274     pos = pc_;
    275     {
    276       uint32_t magic_version = consume_u32("wasm version");
    277       if (magic_version != kWasmVersion) {
    278         error(pos, pos,
    279               "expected version %02x %02x %02x %02x, "
    280               "found %02x %02x %02x %02x",
    281               BYTES(kWasmVersion), BYTES(magic_version));
    282       }
    283     }
    284 
    285     WasmSectionIterator section_iter(*this);
    286 
    287     // ===== Type section ====================================================
    288     if (section_iter.section_code() == kTypeSectionCode) {
    289       uint32_t signatures_count = consume_count("types count", kV8MaxWasmTypes);
    290       module->signatures.reserve(signatures_count);
    291       for (uint32_t i = 0; ok() && i < signatures_count; ++i) {
    292         TRACE("DecodeSignature[%d] module+%d\n", i,
    293               static_cast<int>(pc_ - start_));
    294         FunctionSig* s = consume_sig();
    295         module->signatures.push_back(s);
    296       }
    297       section_iter.advance();
    298     }
    299 
    300     // ===== Import section ==================================================
    301     if (section_iter.section_code() == kImportSectionCode) {
    302       uint32_t import_table_count =
    303           consume_count("imports count", kV8MaxWasmImports);
    304       module->import_table.reserve(import_table_count);
    305       for (uint32_t i = 0; ok() && i < import_table_count; ++i) {
    306         TRACE("DecodeImportTable[%d] module+%d\n", i,
    307               static_cast<int>(pc_ - start_));
    308 
    309         module->import_table.push_back({
    310             0,                  // module_name_length
    311             0,                  // module_name_offset
    312             0,                  // field_name_offset
    313             0,                  // field_name_length
    314             kExternalFunction,  // kind
    315             0                   // index
    316         });
    317         WasmImport* import = &module->import_table.back();
    318         const byte* pos = pc_;
    319         import->module_name_offset =
    320             consume_string(&import->module_name_length, true);
    321         import->field_name_offset =
    322             consume_string(&import->field_name_length, true);
    323 
    324         import->kind = static_cast<WasmExternalKind>(consume_u8("import kind"));
    325         switch (import->kind) {
    326           case kExternalFunction: {
    327             // ===== Imported function =======================================
    328             import->index = static_cast<uint32_t>(module->functions.size());
    329             module->num_imported_functions++;
    330             module->functions.push_back({nullptr,        // sig
    331                                          import->index,  // func_index
    332                                          0,              // sig_index
    333                                          0,              // name_offset
    334                                          0,              // name_length
    335                                          0,              // code_start_offset
    336                                          0,              // code_end_offset
    337                                          true,           // imported
    338                                          false});        // exported
    339             WasmFunction* function = &module->functions.back();
    340             function->sig_index = consume_sig_index(module, &function->sig);
    341             break;
    342           }
    343           case kExternalTable: {
    344             // ===== Imported table ==========================================
    345             if (!AddTable(module)) break;
    346             import->index =
    347                 static_cast<uint32_t>(module->function_tables.size());
    348             module->function_tables.push_back({0, 0, false,
    349                                                std::vector<int32_t>(), true,
    350                                                false, SignatureMap()});
    351             expect_u8("element type", kWasmAnyFunctionTypeForm);
    352             WasmIndirectFunctionTable* table = &module->function_tables.back();
    353             consume_resizable_limits("element count", "elements",
    354                                      FLAG_wasm_max_table_size, &table->min_size,
    355                                      &table->has_max, FLAG_wasm_max_table_size,
    356                                      &table->max_size);
    357             break;
    358           }
    359           case kExternalMemory: {
    360             // ===== Imported memory =========================================
    361             if (!AddMemory(module)) break;
    362             consume_resizable_limits(
    363                 "memory", "pages", FLAG_wasm_max_mem_pages,
    364                 &module->min_mem_pages, &module->has_max_mem,
    365                 kSpecMaxWasmMemoryPages, &module->max_mem_pages);
    366             break;
    367           }
    368           case kExternalGlobal: {
    369             // ===== Imported global =========================================
    370             import->index = static_cast<uint32_t>(module->globals.size());
    371             module->globals.push_back(
    372                 {kWasmStmt, false, WasmInitExpr(), 0, true, false});
    373             WasmGlobal* global = &module->globals.back();
    374             global->type = consume_value_type();
    375             global->mutability = consume_mutability();
    376             if (global->mutability) {
    377               error("mutable globals cannot be imported");
    378             }
    379             break;
    380           }
    381           default:
    382             error(pos, pos, "unknown import kind 0x%02x", import->kind);
    383             break;
    384         }
    385       }
    386       section_iter.advance();
    387     }
    388 
    389     // ===== Function section ================================================
    390     if (section_iter.section_code() == kFunctionSectionCode) {
    391       uint32_t functions_count =
    392           consume_count("functions count", kV8MaxWasmFunctions);
    393       module->functions.reserve(functions_count);
    394       module->num_declared_functions = functions_count;
    395       for (uint32_t i = 0; ok() && i < functions_count; ++i) {
    396         uint32_t func_index = static_cast<uint32_t>(module->functions.size());
    397         module->functions.push_back({nullptr,     // sig
    398                                      func_index,  // func_index
    399                                      0,           // sig_index
    400                                      0,           // name_offset
    401                                      0,           // name_length
    402                                      0,           // code_start_offset
    403                                      0,           // code_end_offset
    404                                      false,       // imported
    405                                      false});     // exported
    406         WasmFunction* function = &module->functions.back();
    407         function->sig_index = consume_sig_index(module, &function->sig);
    408       }
    409       section_iter.advance();
    410     }
    411 
    412     // ===== Table section ===================================================
    413     if (section_iter.section_code() == kTableSectionCode) {
    414       uint32_t table_count = consume_count("table count", kV8MaxWasmTables);
    415 
    416       for (uint32_t i = 0; ok() && i < table_count; i++) {
    417         if (!AddTable(module)) break;
    418         module->function_tables.push_back({0, 0, false, std::vector<int32_t>(),
    419                                            false, false, SignatureMap()});
    420         WasmIndirectFunctionTable* table = &module->function_tables.back();
    421         expect_u8("table type", kWasmAnyFunctionTypeForm);
    422         consume_resizable_limits("table elements", "elements",
    423                                  FLAG_wasm_max_table_size, &table->min_size,
    424                                  &table->has_max, FLAG_wasm_max_table_size,
    425                                  &table->max_size);
    426       }
    427       section_iter.advance();
    428     }
    429 
    430     // ===== Memory section ==================================================
    431     if (section_iter.section_code() == kMemorySectionCode) {
    432       uint32_t memory_count = consume_count("memory count", kV8MaxWasmMemories);
    433 
    434       for (uint32_t i = 0; ok() && i < memory_count; i++) {
    435         if (!AddMemory(module)) break;
    436         consume_resizable_limits("memory", "pages", FLAG_wasm_max_mem_pages,
    437                                  &module->min_mem_pages, &module->has_max_mem,
    438                                  kSpecMaxWasmMemoryPages,
    439                                  &module->max_mem_pages);
    440       }
    441       section_iter.advance();
    442     }
    443 
    444     // ===== Global section ==================================================
    445     if (section_iter.section_code() == kGlobalSectionCode) {
    446       uint32_t globals_count =
    447           consume_count("globals count", kV8MaxWasmGlobals);
    448       uint32_t imported_globals = static_cast<uint32_t>(module->globals.size());
    449       module->globals.reserve(imported_globals + globals_count);
    450       for (uint32_t i = 0; ok() && i < globals_count; ++i) {
    451         TRACE("DecodeGlobal[%d] module+%d\n", i,
    452               static_cast<int>(pc_ - start_));
    453         // Add an uninitialized global and pass a pointer to it.
    454         module->globals.push_back(
    455             {kWasmStmt, false, WasmInitExpr(), 0, false, false});
    456         WasmGlobal* global = &module->globals.back();
    457         DecodeGlobalInModule(module, i + imported_globals, global);
    458       }
    459       section_iter.advance();
    460     }
    461 
    462     // ===== Export section ==================================================
    463     if (section_iter.section_code() == kExportSectionCode) {
    464       uint32_t export_table_count =
    465           consume_count("exports count", kV8MaxWasmImports);
    466       module->export_table.reserve(export_table_count);
    467       for (uint32_t i = 0; ok() && i < export_table_count; ++i) {
    468         TRACE("DecodeExportTable[%d] module+%d\n", i,
    469               static_cast<int>(pc_ - start_));
    470 
    471         module->export_table.push_back({
    472             0,                  // name_length
    473             0,                  // name_offset
    474             kExternalFunction,  // kind
    475             0                   // index
    476         });
    477         WasmExport* exp = &module->export_table.back();
    478 
    479         exp->name_offset = consume_string(&exp->name_length, true);
    480         const byte* pos = pc();
    481         exp->kind = static_cast<WasmExternalKind>(consume_u8("export kind"));
    482         switch (exp->kind) {
    483           case kExternalFunction: {
    484             WasmFunction* func = nullptr;
    485             exp->index = consume_func_index(module, &func);
    486             module->num_exported_functions++;
    487             if (func) func->exported = true;
    488             break;
    489           }
    490           case kExternalTable: {
    491             WasmIndirectFunctionTable* table = nullptr;
    492             exp->index = consume_table_index(module, &table);
    493             if (table) table->exported = true;
    494             break;
    495           }
    496           case kExternalMemory: {
    497             uint32_t index = consume_u32v("memory index");
    498             // TODO(titzer): This should become more regular
    499             // once we support multiple memories.
    500             if (!module->has_memory || index != 0) {
    501               error("invalid memory index != 0");
    502             }
    503             module->mem_export = true;
    504             break;
    505           }
    506           case kExternalGlobal: {
    507             WasmGlobal* global = nullptr;
    508             exp->index = consume_global_index(module, &global);
    509             if (global) {
    510               if (global->mutability) {
    511                 error("mutable globals cannot be exported");
    512               }
    513               global->exported = true;
    514             }
    515             break;
    516           }
    517           default:
    518             error(pos, pos, "invalid export kind 0x%02x", exp->kind);
    519             break;
    520         }
    521       }
    522       // Check for duplicate exports (except for asm.js).
    523       if (ok() && origin_ != kAsmJsOrigin && module->export_table.size() > 1) {
    524         std::vector<WasmExport> sorted_exports(module->export_table);
    525         const byte* base = start_;
    526         auto cmp_less = [base](const WasmExport& a, const WasmExport& b) {
    527           // Return true if a < b.
    528           if (a.name_length != b.name_length) {
    529             return a.name_length < b.name_length;
    530           }
    531           return memcmp(base + a.name_offset, base + b.name_offset,
    532                         a.name_length) < 0;
    533         };
    534         std::stable_sort(sorted_exports.begin(), sorted_exports.end(),
    535                          cmp_less);
    536         auto it = sorted_exports.begin();
    537         WasmExport* last = &*it++;
    538         for (auto end = sorted_exports.end(); it != end; last = &*it++) {
    539           DCHECK(!cmp_less(*it, *last));  // Vector must be sorted.
    540           if (!cmp_less(*last, *it)) {
    541             const byte* pc = start_ + it->name_offset;
    542             error(pc, pc,
    543                   "Duplicate export name '%.*s' for functions %d and %d",
    544                   it->name_length, pc, last->index, it->index);
    545             break;
    546           }
    547         }
    548       }
    549       section_iter.advance();
    550     }
    551 
    552     // ===== Start section ===================================================
    553     if (section_iter.section_code() == kStartSectionCode) {
    554       WasmFunction* func;
    555       const byte* pos = pc_;
    556       module->start_function_index = consume_func_index(module, &func);
    557       if (func &&
    558           (func->sig->parameter_count() > 0 || func->sig->return_count() > 0)) {
    559         error(pos,
    560               "invalid start function: non-zero parameter or return count");
    561       }
    562       section_iter.advance();
    563     }
    564 
    565     // ===== Elements section ================================================
    566     if (section_iter.section_code() == kElementSectionCode) {
    567       uint32_t element_count =
    568           consume_count("element count", FLAG_wasm_max_table_size);
    569       for (uint32_t i = 0; ok() && i < element_count; ++i) {
    570         const byte* pos = pc();
    571         uint32_t table_index = consume_u32v("table index");
    572         if (table_index != 0) {
    573           error(pos, pos, "illegal table index %u != 0", table_index);
    574         }
    575         WasmIndirectFunctionTable* table = nullptr;
    576         if (table_index >= module->function_tables.size()) {
    577           error(pos, pos, "out of bounds table index %u", table_index);
    578         } else {
    579           table = &module->function_tables[table_index];
    580         }
    581         WasmInitExpr offset = consume_init_expr(module, kWasmI32);
    582         uint32_t num_elem =
    583             consume_count("number of elements", kV8MaxWasmTableEntries);
    584         std::vector<uint32_t> vector;
    585         module->table_inits.push_back({table_index, offset, vector});
    586         WasmTableInit* init = &module->table_inits.back();
    587         for (uint32_t j = 0; ok() && j < num_elem; j++) {
    588           WasmFunction* func = nullptr;
    589           uint32_t index = consume_func_index(module, &func);
    590           init->entries.push_back(index);
    591           if (table && index < module->functions.size()) {
    592             // Canonicalize signature indices during decoding.
    593             table->map.FindOrInsert(module->functions[index].sig);
    594           }
    595         }
    596       }
    597 
    598       section_iter.advance();
    599     }
    600 
    601     // ===== Code section ====================================================
    602     if (section_iter.section_code() == kCodeSectionCode) {
    603       const byte* pos = pc_;
    604       uint32_t functions_count = consume_u32v("functions count");
    605       if (functions_count != module->num_declared_functions) {
    606         error(pos, pos, "function body count %u mismatch (%u expected)",
    607               functions_count, module->num_declared_functions);
    608       }
    609       for (uint32_t i = 0; ok() && i < functions_count; ++i) {
    610         WasmFunction* function =
    611             &module->functions[i + module->num_imported_functions];
    612         uint32_t size = consume_u32v("body size");
    613         function->code_start_offset = pc_offset();
    614         function->code_end_offset = pc_offset() + size;
    615         if (verify_functions) {
    616           ModuleBytesEnv module_env(module, nullptr,
    617                                     ModuleWireBytes(start_, end_));
    618           VerifyFunctionBody(i + module->num_imported_functions, &module_env,
    619                              function);
    620         }
    621         consume_bytes(size, "function body");
    622       }
    623       section_iter.advance();
    624     }
    625 
    626     // ===== Data section ====================================================
    627     if (section_iter.section_code() == kDataSectionCode) {
    628       uint32_t data_segments_count =
    629           consume_count("data segments count", kV8MaxWasmDataSegments);
    630       module->data_segments.reserve(data_segments_count);
    631       for (uint32_t i = 0; ok() && i < data_segments_count; ++i) {
    632         if (!module->has_memory) {
    633           error("cannot load data without memory");
    634           break;
    635         }
    636         TRACE("DecodeDataSegment[%d] module+%d\n", i,
    637               static_cast<int>(pc_ - start_));
    638         module->data_segments.push_back({
    639             WasmInitExpr(),  // dest_addr
    640             0,               // source_offset
    641             0                // source_size
    642         });
    643         WasmDataSegment* segment = &module->data_segments.back();
    644         DecodeDataSegmentInModule(module, segment);
    645       }
    646       section_iter.advance();
    647     }
    648 
    649     // ===== Name section ====================================================
    650     if (section_iter.section_code() == kNameSectionCode) {
    651       // TODO(titzer): find a way to report name errors as warnings.
    652       // Use an inner decoder so that errors don't fail the outer decoder.
    653       Decoder inner(start_, pc_, end_);
    654       uint32_t functions_count = inner.consume_u32v("functions count");
    655 
    656       for (uint32_t i = 0; inner.ok() && i < functions_count; ++i) {
    657         uint32_t function_name_length = 0;
    658         uint32_t name_offset =
    659             consume_string(inner, &function_name_length, false);
    660         uint32_t func_index = i;
    661         if (inner.ok() && func_index < module->functions.size()) {
    662           module->functions[func_index].name_offset = name_offset;
    663           module->functions[func_index].name_length = function_name_length;
    664         }
    665 
    666         uint32_t local_names_count = inner.consume_u32v("local names count");
    667         for (uint32_t j = 0; inner.ok() && j < local_names_count; j++) {
    668           uint32_t length = inner.consume_u32v("string length");
    669           inner.consume_bytes(length, "string");
    670         }
    671       }
    672       // Skip the whole names section in the outer decoder.
    673       consume_bytes(section_iter.payload_length(), nullptr);
    674       section_iter.advance();
    675     }
    676 
    677     // ===== Remaining sections ==============================================
    678     if (section_iter.more() && ok()) {
    679       error(pc(), pc(), "unexpected section: %s",
    680             SectionName(section_iter.section_code()));
    681     }
    682 
    683     if (ok()) {
    684       CalculateGlobalOffsets(module);
    685     }
    686     const WasmModule* finished_module = module;
    687     ModuleResult result = toResult(finished_module);
    688     if (verify_functions && result.ok()) {
    689       result.MoveFrom(result_);  // Copy error code and location.
    690     }
    691     if (FLAG_dump_wasm_module) DumpModule(result);
    692     return result;
    693   }
    694 
    695   // Decodes a single anonymous function starting at {start_}.
    696   FunctionResult DecodeSingleFunction(ModuleBytesEnv* module_env,
    697                                       WasmFunction* function) {
    698     pc_ = start_;
    699     function->sig = consume_sig();            // read signature
    700     function->name_offset = 0;                // ---- name
    701     function->name_length = 0;                // ---- name length
    702     function->code_start_offset = off(pc_);   // ---- code start
    703     function->code_end_offset = off(end_);    // ---- code end
    704 
    705     if (ok()) VerifyFunctionBody(0, module_env, function);
    706 
    707     FunctionResult result;
    708     result.MoveFrom(result_);  // Copy error code and location.
    709     result.val = function;
    710     return result;
    711   }
    712 
    713   // Decodes a single function signature at {start}.
    714   FunctionSig* DecodeFunctionSignature(const byte* start) {
    715     pc_ = start;
    716     FunctionSig* result = consume_sig();
    717     return ok() ? result : nullptr;
    718   }
    719 
    720   WasmInitExpr DecodeInitExpr(const byte* start) {
    721     pc_ = start;
    722     return consume_init_expr(nullptr, kWasmStmt);
    723   }
    724 
    725  private:
    726   Zone* module_zone;
    727   ModuleResult result_;
    728   ModuleOrigin origin_;
    729 
    730   uint32_t off(const byte* ptr) { return static_cast<uint32_t>(ptr - start_); }
    731 
    732   bool AddTable(WasmModule* module) {
    733     if (module->function_tables.size() > 0) {
    734       error("At most one table is supported");
    735       return false;
    736     } else {
    737       return true;
    738     }
    739   }
    740 
    741   bool AddMemory(WasmModule* module) {
    742     if (module->has_memory) {
    743       error("At most one memory is supported");
    744       return false;
    745     } else {
    746       module->has_memory = true;
    747       return true;
    748     }
    749   }
    750 
    751   // Decodes a single global entry inside a module starting at {pc_}.
    752   void DecodeGlobalInModule(WasmModule* module, uint32_t index,
    753                             WasmGlobal* global) {
    754     global->type = consume_value_type();
    755     global->mutability = consume_mutability();
    756     const byte* pos = pc();
    757     global->init = consume_init_expr(module, kWasmStmt);
    758     switch (global->init.kind) {
    759       case WasmInitExpr::kGlobalIndex: {
    760         uint32_t other_index = global->init.val.global_index;
    761         if (other_index >= index) {
    762           error(pos, pos,
    763                 "invalid global index in init expression, "
    764                 "index %u, other_index %u",
    765                 index, other_index);
    766         } else if (module->globals[other_index].type != global->type) {
    767           error(pos, pos,
    768                 "type mismatch in global initialization "
    769                 "(from global #%u), expected %s, got %s",
    770                 other_index, WasmOpcodes::TypeName(global->type),
    771                 WasmOpcodes::TypeName(module->globals[other_index].type));
    772         }
    773         break;
    774       }
    775       default:
    776         if (global->type != TypeOf(module, global->init)) {
    777           error(pos, pos,
    778                 "type error in global initialization, expected %s, got %s",
    779                 WasmOpcodes::TypeName(global->type),
    780                 WasmOpcodes::TypeName(TypeOf(module, global->init)));
    781         }
    782     }
    783   }
    784 
    785   bool IsWithinLimit(uint32_t limit, uint32_t offset, uint32_t size) {
    786     if (offset > limit) return false;
    787     if ((offset + size) < offset) return false;  // overflow
    788     return (offset + size) <= limit;
    789   }
    790 
    791   // Decodes a single data segment entry inside a module starting at {pc_}.
    792   void DecodeDataSegmentInModule(WasmModule* module, WasmDataSegment* segment) {
    793     const byte* start = pc_;
    794     expect_u8("linear memory index", 0);
    795     segment->dest_addr = consume_init_expr(module, kWasmI32);
    796     segment->source_size = consume_u32v("source size");
    797     segment->source_offset = static_cast<uint32_t>(pc_ - start_);
    798 
    799     // Validate the data is in the module.
    800     uint32_t module_limit = static_cast<uint32_t>(end_ - start_);
    801     if (!IsWithinLimit(module_limit, segment->source_offset,
    802                        segment->source_size)) {
    803       error(start, "segment out of bounds of module");
    804     }
    805 
    806     consume_bytes(segment->source_size, "segment data");
    807   }
    808 
    809   // Calculate individual global offsets and total size of globals table.
    810   void CalculateGlobalOffsets(WasmModule* module) {
    811     uint32_t offset = 0;
    812     if (module->globals.size() == 0) {
    813       module->globals_size = 0;
    814       return;
    815     }
    816     for (WasmGlobal& global : module->globals) {
    817       byte size =
    818           WasmOpcodes::MemSize(WasmOpcodes::MachineTypeFor(global.type));
    819       offset = (offset + size - 1) & ~(size - 1);  // align
    820       global.offset = offset;
    821       offset += size;
    822     }
    823     module->globals_size = offset;
    824   }
    825 
    826   // Verifies the body (code) of a given function.
    827   void VerifyFunctionBody(uint32_t func_num, ModuleBytesEnv* menv,
    828                           WasmFunction* function) {
    829     WasmFunctionName func_name(function,
    830                                menv->wire_bytes.GetNameOrNull(function));
    831     if (FLAG_trace_wasm_decoder || FLAG_trace_wasm_decode_time) {
    832       OFStream os(stdout);
    833       os << "Verifying WASM function " << func_name << std::endl;
    834     }
    835     FunctionBody body = {function->sig, start_,
    836                          start_ + function->code_start_offset,
    837                          start_ + function->code_end_offset};
    838     DecodeResult result = VerifyWasmCode(
    839         module_zone->allocator(),
    840         menv == nullptr ? nullptr : menv->module_env.module, body);
    841     if (result.failed()) {
    842       // Wrap the error message from the function decoder.
    843       std::ostringstream str;
    844       str << "in function " << func_name << ": ";
    845       str << result;
    846       std::string strval = str.str();
    847       const char* raw = strval.c_str();
    848       size_t len = strlen(raw);
    849       char* buffer = new char[len];
    850       strncpy(buffer, raw, len);
    851       buffer[len - 1] = 0;
    852 
    853       // Copy error code and location.
    854       result_.MoveFrom(result);
    855       result_.error_msg.reset(buffer);
    856     }
    857   }
    858 
    859   uint32_t consume_string(uint32_t* length, bool validate_utf8) {
    860     return consume_string(*this, length, validate_utf8);
    861   }
    862 
    863   // Reads a length-prefixed string, checking that it is within bounds. Returns
    864   // the offset of the string, and the length as an out parameter.
    865   uint32_t consume_string(Decoder& decoder, uint32_t* length,
    866                           bool validate_utf8) {
    867     *length = decoder.consume_u32v("string length");
    868     uint32_t offset = decoder.pc_offset();
    869     const byte* string_start = decoder.pc();
    870     // Consume bytes before validation to guarantee that the string is not oob.
    871     if (*length > 0) decoder.consume_bytes(*length, "string");
    872     if (decoder.ok() && validate_utf8 &&
    873         !unibrow::Utf8::Validate(string_start, *length)) {
    874       decoder.error(string_start, "no valid UTF-8 string");
    875     }
    876     return offset;
    877   }
    878 
    879   uint32_t consume_sig_index(WasmModule* module, FunctionSig** sig) {
    880     const byte* pos = pc_;
    881     uint32_t sig_index = consume_u32v("signature index");
    882     if (sig_index >= module->signatures.size()) {
    883       error(pos, pos, "signature index %u out of bounds (%d signatures)",
    884             sig_index, static_cast<int>(module->signatures.size()));
    885       *sig = nullptr;
    886       return 0;
    887     }
    888     *sig = module->signatures[sig_index];
    889     return sig_index;
    890   }
    891 
    892   uint32_t consume_count(const char* name, size_t maximum) {
    893     const byte* p = pc_;
    894     uint32_t count = consume_u32v(name);
    895     if (count > maximum) {
    896       error(p, p, "%s of %u exceeds internal limit of %zu", name, count,
    897             maximum);
    898       return static_cast<uint32_t>(maximum);
    899     }
    900     return count;
    901   }
    902 
    903   uint32_t consume_func_index(WasmModule* module, WasmFunction** func) {
    904     return consume_index("function index", module->functions, func);
    905   }
    906 
    907   uint32_t consume_global_index(WasmModule* module, WasmGlobal** global) {
    908     return consume_index("global index", module->globals, global);
    909   }
    910 
    911   uint32_t consume_table_index(WasmModule* module,
    912                                WasmIndirectFunctionTable** table) {
    913     return consume_index("table index", module->function_tables, table);
    914   }
    915 
    916   template <typename T>
    917   uint32_t consume_index(const char* name, std::vector<T>& vector, T** ptr) {
    918     const byte* pos = pc_;
    919     uint32_t index = consume_u32v(name);
    920     if (index >= vector.size()) {
    921       error(pos, pos, "%s %u out of bounds (%d entries)", name, index,
    922             static_cast<int>(vector.size()));
    923       *ptr = nullptr;
    924       return 0;
    925     }
    926     *ptr = &vector[index];
    927     return index;
    928   }
    929 
    930   void consume_resizable_limits(const char* name, const char* units,
    931                                 uint32_t max_initial, uint32_t* initial,
    932                                 bool* has_max, uint32_t max_maximum,
    933                                 uint32_t* maximum) {
    934     uint32_t flags = consume_u32v("resizable limits flags");
    935     const byte* pos = pc();
    936     *initial = consume_u32v("initial size");
    937     *has_max = false;
    938     if (*initial > max_initial) {
    939       error(pos, pos,
    940             "initial %s size (%u %s) is larger than implementation limit (%u)",
    941             name, *initial, units, max_initial);
    942     }
    943     if (flags & 1) {
    944       *has_max = true;
    945       pos = pc();
    946       *maximum = consume_u32v("maximum size");
    947       if (*maximum > max_maximum) {
    948         error(
    949             pos, pos,
    950             "maximum %s size (%u %s) is larger than implementation limit (%u)",
    951             name, *maximum, units, max_maximum);
    952       }
    953       if (*maximum < *initial) {
    954         error(pos, pos, "maximum %s size (%u %s) is less than initial (%u %s)",
    955               name, *maximum, units, *initial, units);
    956       }
    957     } else {
    958       *has_max = false;
    959       *maximum = max_initial;
    960     }
    961   }
    962 
    963   bool expect_u8(const char* name, uint8_t expected) {
    964     const byte* pos = pc();
    965     uint8_t value = consume_u8(name);
    966     if (value != expected) {
    967       error(pos, pos, "expected %s 0x%02x, got 0x%02x", name, expected, value);
    968       return false;
    969     }
    970     return true;
    971   }
    972 
    973   WasmInitExpr consume_init_expr(WasmModule* module, ValueType expected) {
    974     const byte* pos = pc();
    975     uint8_t opcode = consume_u8("opcode");
    976     WasmInitExpr expr;
    977     unsigned len = 0;
    978     switch (opcode) {
    979       case kExprGetGlobal: {
    980         GlobalIndexOperand operand(this, pc() - 1);
    981         if (module->globals.size() <= operand.index) {
    982           error("global index is out of bounds");
    983           expr.kind = WasmInitExpr::kNone;
    984           expr.val.i32_const = 0;
    985           break;
    986         }
    987         WasmGlobal* global = &module->globals[operand.index];
    988         if (global->mutability || !global->imported) {
    989           error(
    990               "only immutable imported globals can be used in initializer "
    991               "expressions");
    992           expr.kind = WasmInitExpr::kNone;
    993           expr.val.i32_const = 0;
    994           break;
    995         }
    996         expr.kind = WasmInitExpr::kGlobalIndex;
    997         expr.val.global_index = operand.index;
    998         len = operand.length;
    999         break;
   1000       }
   1001       case kExprI32Const: {
   1002         ImmI32Operand operand(this, pc() - 1);
   1003         expr.kind = WasmInitExpr::kI32Const;
   1004         expr.val.i32_const = operand.value;
   1005         len = operand.length;
   1006         break;
   1007       }
   1008       case kExprF32Const: {
   1009         ImmF32Operand operand(this, pc() - 1);
   1010         expr.kind = WasmInitExpr::kF32Const;
   1011         expr.val.f32_const = operand.value;
   1012         len = operand.length;
   1013         break;
   1014       }
   1015       case kExprI64Const: {
   1016         ImmI64Operand operand(this, pc() - 1);
   1017         expr.kind = WasmInitExpr::kI64Const;
   1018         expr.val.i64_const = operand.value;
   1019         len = operand.length;
   1020         break;
   1021       }
   1022       case kExprF64Const: {
   1023         ImmF64Operand operand(this, pc() - 1);
   1024         expr.kind = WasmInitExpr::kF64Const;
   1025         expr.val.f64_const = operand.value;
   1026         len = operand.length;
   1027         break;
   1028       }
   1029       default: {
   1030         error("invalid opcode in initialization expression");
   1031         expr.kind = WasmInitExpr::kNone;
   1032         expr.val.i32_const = 0;
   1033       }
   1034     }
   1035     consume_bytes(len, "init code");
   1036     if (!expect_u8("end opcode", kExprEnd)) {
   1037       expr.kind = WasmInitExpr::kNone;
   1038     }
   1039     if (expected != kWasmStmt && TypeOf(module, expr) != kWasmI32) {
   1040       error(pos, pos, "type error in init expression, expected %s, got %s",
   1041             WasmOpcodes::TypeName(expected),
   1042             WasmOpcodes::TypeName(TypeOf(module, expr)));
   1043     }
   1044     return expr;
   1045   }
   1046 
   1047   // Read a mutability flag
   1048   bool consume_mutability() {
   1049     byte val = consume_u8("mutability");
   1050     if (val > 1) error(pc_ - 1, "invalid mutability");
   1051     return val != 0;
   1052   }
   1053 
   1054   // Reads a single 8-bit integer, interpreting it as a local type.
   1055   ValueType consume_value_type() {
   1056     byte val = consume_u8("value type");
   1057     ValueTypeCode t = static_cast<ValueTypeCode>(val);
   1058     switch (t) {
   1059       case kLocalI32:
   1060         return kWasmI32;
   1061       case kLocalI64:
   1062         return kWasmI64;
   1063       case kLocalF32:
   1064         return kWasmF32;
   1065       case kLocalF64:
   1066         return kWasmF64;
   1067       default:
   1068         if (origin_ != kAsmJsOrigin && FLAG_wasm_simd_prototype) {
   1069           switch (t) {
   1070             case kLocalS128:
   1071               return kWasmS128;
   1072             case kLocalS1x4:
   1073               return kWasmS1x4;
   1074             case kLocalS1x8:
   1075               return kWasmS1x8;
   1076             case kLocalS1x16:
   1077               return kWasmS1x16;
   1078             default:
   1079               break;
   1080           }
   1081         }
   1082         error(pc_ - 1, "invalid local type");
   1083         return kWasmStmt;
   1084     }
   1085   }
   1086 
   1087   // Parses a type entry, which is currently limited to functions only.
   1088   FunctionSig* consume_sig() {
   1089     if (!expect_u8("type form", kWasmFunctionTypeForm)) return nullptr;
   1090     // parse parameter types
   1091     uint32_t param_count =
   1092         consume_count("param count", kV8MaxWasmFunctionParams);
   1093     if (failed()) return nullptr;
   1094     std::vector<ValueType> params;
   1095     for (uint32_t i = 0; ok() && i < param_count; ++i) {
   1096       ValueType param = consume_value_type();
   1097       params.push_back(param);
   1098     }
   1099 
   1100     // parse return types
   1101     const size_t max_return_count = FLAG_wasm_mv_prototype
   1102                                         ? kV8MaxWasmFunctionMultiReturns
   1103                                         : kV8MaxWasmFunctionReturns;
   1104     uint32_t return_count = consume_count("return count", max_return_count);
   1105     if (failed()) return nullptr;
   1106     std::vector<ValueType> returns;
   1107     for (uint32_t i = 0; ok() && i < return_count; ++i) {
   1108       ValueType ret = consume_value_type();
   1109       returns.push_back(ret);
   1110     }
   1111 
   1112     if (failed()) return nullptr;
   1113 
   1114     // FunctionSig stores the return types first.
   1115     ValueType* buffer =
   1116         module_zone->NewArray<ValueType>(param_count + return_count);
   1117     uint32_t b = 0;
   1118     for (uint32_t i = 0; i < return_count; ++i) buffer[b++] = returns[i];
   1119     for (uint32_t i = 0; i < param_count; ++i) buffer[b++] = params[i];
   1120 
   1121     return new (module_zone) FunctionSig(return_count, param_count, buffer);
   1122   }
   1123 };
   1124 
   1125 // Helpers for nice error messages.
   1126 class ModuleError : public ModuleResult {
   1127  public:
   1128   explicit ModuleError(const char* msg) {
   1129     error_code = kError;
   1130     size_t len = strlen(msg) + 1;
   1131     char* result = new char[len];
   1132     strncpy(result, msg, len);
   1133     result[len - 1] = 0;
   1134     error_msg.reset(result);
   1135   }
   1136 };
   1137 
   1138 // Helpers for nice error messages.
   1139 class FunctionError : public FunctionResult {
   1140  public:
   1141   explicit FunctionError(const char* msg) {
   1142     error_code = kError;
   1143     size_t len = strlen(msg) + 1;
   1144     char* result = new char[len];
   1145     strncpy(result, msg, len);
   1146     result[len - 1] = 0;
   1147     error_msg.reset(result);
   1148   }
   1149 };
   1150 
   1151 // Find section with given section code. Return Vector of the payload, or null
   1152 // Vector if section is not found or module bytes are invalid.
   1153 Vector<const byte> FindSection(const byte* module_start, const byte* module_end,
   1154                                WasmSectionCode code) {
   1155   Decoder decoder(module_start, module_end);
   1156 
   1157   uint32_t magic_word = decoder.consume_u32("wasm magic");
   1158   if (magic_word != kWasmMagic) decoder.error("wrong magic word");
   1159 
   1160   uint32_t magic_version = decoder.consume_u32("wasm version");
   1161   if (magic_version != kWasmVersion) decoder.error("wrong wasm version");
   1162 
   1163   WasmSectionIterator section_iter(decoder);
   1164   while (section_iter.more()) {
   1165     if (section_iter.section_code() == code) {
   1166       return Vector<const uint8_t>(section_iter.payload_start(),
   1167                                    section_iter.payload_length());
   1168     }
   1169     decoder.consume_bytes(section_iter.payload_length(), "section payload");
   1170     section_iter.advance();
   1171   }
   1172 
   1173   return Vector<const uint8_t>();
   1174 }
   1175 
   1176 }  // namespace
   1177 
   1178 ModuleResult DecodeWasmModule(Isolate* isolate, const byte* module_start,
   1179                               const byte* module_end, bool verify_functions,
   1180                               ModuleOrigin origin) {
   1181   HistogramTimerScope wasm_decode_module_time_scope(
   1182       isolate->counters()->wasm_decode_module_time());
   1183   size_t size = module_end - module_start;
   1184   if (module_start > module_end) return ModuleError("start > end");
   1185   if (size >= kV8MaxWasmModuleSize)
   1186     return ModuleError("size > maximum module size");
   1187   // TODO(bradnelson): Improve histogram handling of size_t.
   1188   isolate->counters()->wasm_module_size_bytes()->AddSample(
   1189       static_cast<int>(size));
   1190   // Signatures are stored in zone memory, which have the same lifetime
   1191   // as the {module}.
   1192   Zone* zone = new Zone(isolate->allocator(), ZONE_NAME);
   1193   ModuleDecoder decoder(zone, module_start, module_end, origin);
   1194   ModuleResult result = decoder.DecodeModule(verify_functions);
   1195   // TODO(bradnelson): Improve histogram handling of size_t.
   1196   // TODO(titzer): this isn't accurate, since it doesn't count the data
   1197   // allocated on the C++ heap.
   1198   // https://bugs.chromium.org/p/chromium/issues/detail?id=657320
   1199   isolate->counters()->wasm_decode_module_peak_memory_bytes()->AddSample(
   1200       static_cast<int>(zone->allocation_size()));
   1201   return result;
   1202 }
   1203 
   1204 FunctionSig* DecodeWasmSignatureForTesting(Zone* zone, const byte* start,
   1205                                            const byte* end) {
   1206   ModuleDecoder decoder(zone, start, end, kWasmOrigin);
   1207   return decoder.DecodeFunctionSignature(start);
   1208 }
   1209 
   1210 WasmInitExpr DecodeWasmInitExprForTesting(const byte* start, const byte* end) {
   1211   AccountingAllocator allocator;
   1212   Zone zone(&allocator, ZONE_NAME);
   1213   ModuleDecoder decoder(&zone, start, end, kWasmOrigin);
   1214   return decoder.DecodeInitExpr(start);
   1215 }
   1216 
   1217 FunctionResult DecodeWasmFunction(Isolate* isolate, Zone* zone,
   1218                                   ModuleBytesEnv* module_env,
   1219                                   const byte* function_start,
   1220                                   const byte* function_end) {
   1221   HistogramTimerScope wasm_decode_function_time_scope(
   1222       isolate->counters()->wasm_decode_function_time());
   1223   size_t size = function_end - function_start;
   1224   if (function_start > function_end) return FunctionError("start > end");
   1225   if (size > kV8MaxWasmFunctionSize)
   1226     return FunctionError("size > maximum function size");
   1227   isolate->counters()->wasm_function_size_bytes()->AddSample(
   1228       static_cast<int>(size));
   1229   WasmFunction* function = new WasmFunction();
   1230   ModuleDecoder decoder(zone, function_start, function_end, kWasmOrigin);
   1231   return decoder.DecodeSingleFunction(module_env, function);
   1232 }
   1233 
   1234 FunctionOffsetsResult DecodeWasmFunctionOffsets(const byte* module_start,
   1235                                                 const byte* module_end) {
   1236   // Find and decode the code section.
   1237   Vector<const byte> code_section =
   1238       FindSection(module_start, module_end, kCodeSectionCode);
   1239   Decoder decoder(code_section.start(), code_section.end());
   1240   FunctionOffsets table;
   1241   if (!code_section.start()) {
   1242     decoder.error("no code section");
   1243     return decoder.toResult(std::move(table));
   1244   }
   1245 
   1246   uint32_t functions_count = decoder.consume_u32v("functions count");
   1247   // Reserve space for the entries, taking care of invalid input.
   1248   if (functions_count < static_cast<unsigned>(code_section.length()) / 2) {
   1249     table.reserve(functions_count);
   1250   }
   1251 
   1252   int section_offset = static_cast<int>(code_section.start() - module_start);
   1253   DCHECK_LE(0, section_offset);
   1254   for (uint32_t i = 0; i < functions_count && decoder.ok(); ++i) {
   1255     uint32_t size = decoder.consume_u32v("body size");
   1256     int offset = static_cast<int>(section_offset + decoder.pc_offset());
   1257     table.emplace_back(offset, static_cast<int>(size));
   1258     DCHECK(table.back().first >= 0 && table.back().second >= 0);
   1259     decoder.consume_bytes(size);
   1260   }
   1261   if (decoder.more()) decoder.error("unexpected additional bytes");
   1262 
   1263   return decoder.toResult(std::move(table));
   1264 }
   1265 
   1266 AsmJsOffsetsResult DecodeAsmJsOffsets(const byte* tables_start,
   1267                                       const byte* tables_end) {
   1268   AsmJsOffsets table;
   1269 
   1270   Decoder decoder(tables_start, tables_end);
   1271   uint32_t functions_count = decoder.consume_u32v("functions count");
   1272   // Reserve space for the entries, taking care of invalid input.
   1273   if (functions_count < static_cast<unsigned>(tables_end - tables_start)) {
   1274     table.reserve(functions_count);
   1275   }
   1276 
   1277   for (uint32_t i = 0; i < functions_count && decoder.ok(); ++i) {
   1278     uint32_t size = decoder.consume_u32v("table size");
   1279     if (size == 0) {
   1280       table.emplace_back();
   1281       continue;
   1282     }
   1283     if (!decoder.checkAvailable(size)) {
   1284       decoder.error("illegal asm function offset table size");
   1285     }
   1286     const byte* table_end = decoder.pc() + size;
   1287     uint32_t locals_size = decoder.consume_u32v("locals size");
   1288     int function_start_position = decoder.consume_u32v("function start pos");
   1289     int last_byte_offset = locals_size;
   1290     int last_asm_position = function_start_position;
   1291     std::vector<AsmJsOffsetEntry> func_asm_offsets;
   1292     func_asm_offsets.reserve(size / 4);  // conservative estimation
   1293     // Add an entry for the stack check, associated with position 0.
   1294     func_asm_offsets.push_back(
   1295         {0, function_start_position, function_start_position});
   1296     while (decoder.ok() && decoder.pc() < table_end) {
   1297       last_byte_offset += decoder.consume_u32v("byte offset delta");
   1298       int call_position =
   1299           last_asm_position + decoder.consume_i32v("call position delta");
   1300       int to_number_position =
   1301           call_position + decoder.consume_i32v("to_number position delta");
   1302       last_asm_position = to_number_position;
   1303       func_asm_offsets.push_back(
   1304           {last_byte_offset, call_position, to_number_position});
   1305     }
   1306     if (decoder.pc() != table_end) {
   1307       decoder.error("broken asm offset table");
   1308     }
   1309     table.push_back(std::move(func_asm_offsets));
   1310   }
   1311   if (decoder.more()) decoder.error("unexpected additional bytes");
   1312 
   1313   return decoder.toResult(std::move(table));
   1314 }
   1315 
   1316 std::vector<CustomSectionOffset> DecodeCustomSections(const byte* start,
   1317                                                       const byte* end) {
   1318   Decoder decoder(start, end);
   1319   decoder.consume_bytes(4, "wasm magic");
   1320   decoder.consume_bytes(4, "wasm version");
   1321 
   1322   std::vector<CustomSectionOffset> result;
   1323 
   1324   while (decoder.more()) {
   1325     byte section_code = decoder.consume_u8("section code");
   1326     uint32_t section_length = decoder.consume_u32v("section length");
   1327     uint32_t section_start = decoder.pc_offset();
   1328     if (section_code != 0) {
   1329       // Skip known sections.
   1330       decoder.consume_bytes(section_length, "section bytes");
   1331       continue;
   1332     }
   1333     uint32_t name_length = decoder.consume_u32v("name length");
   1334     uint32_t name_offset = decoder.pc_offset();
   1335     decoder.consume_bytes(name_length, "section name");
   1336     uint32_t payload_offset = decoder.pc_offset();
   1337     uint32_t payload_length = section_length - (payload_offset - section_start);
   1338     decoder.consume_bytes(payload_length);
   1339     result.push_back({section_start, name_offset, name_length, payload_offset,
   1340                       payload_length, section_length});
   1341   }
   1342 
   1343   return result;
   1344 }
   1345 
   1346 }  // namespace wasm
   1347 }  // namespace internal
   1348 }  // namespace v8
   1349