2 * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #include "WasmModuleParser.h"
29 #if ENABLE(WEBASSEMBLY)
31 #include "IdentifierInlines.h"
32 #include "WasmMemoryInformation.h"
33 #include "WasmNameSectionParser.h"
35 #include "WasmSections.h"
37 namespace JSC { namespace Wasm {
39 ALWAYS_INLINE I32InitExpr makeI32InitExpr(uint8_t opcode, uint32_t bits)
41 RELEASE_ASSERT(opcode == I32Const || opcode == GetGlobal);
42 if (opcode == I32Const)
43 return I32InitExpr::constValue(bits);
44 return I32InitExpr::globalImport(bits);
47 auto ModuleParser::parse() -> Result
49 const size_t minSize = 8;
50 uint32_t versionNumber;
52 WASM_PARSER_FAIL_IF(length() < minSize, "expected a module of at least ", minSize, " bytes");
53 WASM_PARSER_FAIL_IF(length() > maxModuleSize, "module size ", length(), " is too large, maximum ", maxModuleSize);
54 WASM_PARSER_FAIL_IF(!consumeCharacter(0) || !consumeString("asm"), "modules doesn't start with '\\0asm'");
55 WASM_PARSER_FAIL_IF(!parseUInt32(versionNumber), "can't parse version number");
56 WASM_PARSER_FAIL_IF(versionNumber != expectedVersionNumber, "unexpected version number ", versionNumber, " expected ", expectedVersionNumber);
58 Section previousSection = Section::Custom;
59 while (m_offset < length()) {
62 WASM_PARSER_FAIL_IF(!parseUInt7(sectionByte), "can't get section byte");
64 Section section = Section::Custom;
66 if (isValidSection(sectionByte))
67 section = static_cast<Section>(sectionByte);
70 uint32_t sectionLength;
71 WASM_PARSER_FAIL_IF(!validateOrder(previousSection, section), "invalid section order, ", previousSection, " followed by ", section);
72 WASM_PARSER_FAIL_IF(!parseVarUInt32(sectionLength), "can't get ", section, " section's length");
73 WASM_PARSER_FAIL_IF(sectionLength > length() - m_offset, section, "section of size ", sectionLength, " would overflow Module's size");
75 auto end = m_offset + sectionLength;
78 #define WASM_SECTION_PARSE(NAME, ID, DESCRIPTION) \
79 case Section::NAME: { \
80 WASM_FAIL_IF_HELPER_FAILS(parse ## NAME()); \
83 FOR_EACH_WASM_SECTION(WASM_SECTION_PARSE)
84 #undef WASM_SECTION_PARSE
86 case Section::Custom: {
87 WASM_FAIL_IF_HELPER_FAILS(parseCustom(sectionLength));
92 WASM_PARSER_FAIL_IF(end != m_offset, "parsing ended before the end of ", section, " section");
94 previousSection = section;
100 auto ModuleParser::parseType() -> PartialResult
104 WASM_PARSER_FAIL_IF(!parseVarUInt32(count), "can't get Type section's count");
105 WASM_PARSER_FAIL_IF(count > maxTypes, "Type section's count is too big ", count, " maximum ", maxTypes);
106 WASM_PARSER_FAIL_IF(!m_info->usedSignatures.tryReserveCapacity(count), "can't allocate enough memory for Type section's ", count, " entries");
108 for (uint32_t i = 0; i < count; ++i) {
110 uint32_t argumentCount;
111 Vector<Type> argumentTypes;
113 WASM_PARSER_FAIL_IF(!parseInt7(type), "can't get ", i, "th Type's type");
114 WASM_PARSER_FAIL_IF(type != Func, i, "th Type is non-Func ", type);
115 WASM_PARSER_FAIL_IF(!parseVarUInt32(argumentCount), "can't get ", i, "th Type's argument count");
116 WASM_PARSER_FAIL_IF(argumentCount > maxFunctionParams, i, "th argument count is too big ", argumentCount, " maximum ", maxFunctionParams);
117 RefPtr<Signature> maybeSignature = Signature::tryCreate(argumentCount);
118 WASM_PARSER_FAIL_IF(!maybeSignature, "can't allocate enough memory for Type section's ", i, "th signature");
119 Ref<Signature> signature = maybeSignature.releaseNonNull();
121 for (unsigned i = 0; i < argumentCount; ++i) {
123 WASM_PARSER_FAIL_IF(!parseResultType(argumentType), "can't get ", i, "th argument Type");
124 signature->argument(i) = argumentType;
128 WASM_PARSER_FAIL_IF(!parseVarUInt1(returnCount), "can't get ", i, "th Type's return count");
132 WASM_PARSER_FAIL_IF(!parseValueType(value), "can't get ", i, "th Type's return value");
133 returnType = static_cast<Type>(value);
135 returnType = Type::Void;
136 signature->returnType() = returnType;
138 std::pair<SignatureIndex, Ref<Signature>> result = SignatureInformation::adopt(WTFMove(signature));
139 m_info->usedSignatures.uncheckedAppend(WTFMove(result.second));
144 auto ModuleParser::parseImport() -> PartialResult
146 uint32_t importCount;
147 WASM_PARSER_FAIL_IF(!parseVarUInt32(importCount), "can't get Import section's count");
148 WASM_PARSER_FAIL_IF(importCount > maxImports, "Import section's count is too big ", importCount, " maximum ", maxImports);
149 WASM_PARSER_FAIL_IF(!m_info->globals.tryReserveCapacity(importCount), "can't allocate enough memory for ", importCount, " globals"); // FIXME this over-allocates when we fix the FIXMEs below.
150 WASM_PARSER_FAIL_IF(!m_info->imports.tryReserveCapacity(importCount), "can't allocate enough memory for ", importCount, " imports"); // FIXME this over-allocates when we fix the FIXMEs below.
151 WASM_PARSER_FAIL_IF(!m_info->importFunctionSignatureIndices.tryReserveCapacity(importCount), "can't allocate enough memory for ", importCount, " import function signatures"); // FIXME this over-allocates when we fix the FIXMEs below.
153 for (uint32_t importNumber = 0; importNumber < importCount; ++importNumber) {
159 unsigned kindIndex { 0 };
161 WASM_PARSER_FAIL_IF(!parseVarUInt32(moduleLen), "can't get ", importNumber, "th Import's module name length");
162 WASM_PARSER_FAIL_IF(!consumeUTF8String(moduleString, moduleLen), "can't get ", importNumber, "th Import's module name of length ", moduleLen);
164 WASM_PARSER_FAIL_IF(!parseVarUInt32(fieldLen), "can't get ", importNumber, "th Import's field name length in module '", moduleString, "'");
165 WASM_PARSER_FAIL_IF(!consumeUTF8String(fieldString, fieldLen), "can't get ", importNumber, "th Import's field name of length ", moduleLen, " in module '", moduleString, "'");
167 WASM_PARSER_FAIL_IF(!parseExternalKind(kind), "can't get ", importNumber, "th Import's kind in module '", moduleString, "' field '", fieldString, "'");
169 case ExternalKind::Function: {
170 uint32_t functionSignatureIndex;
171 WASM_PARSER_FAIL_IF(!parseVarUInt32(functionSignatureIndex), "can't get ", importNumber, "th Import's function signature in module '", moduleString, "' field '", fieldString, "'");
172 WASM_PARSER_FAIL_IF(functionSignatureIndex >= m_info->usedSignatures.size(), "invalid function signature for ", importNumber, "th Import, ", functionSignatureIndex, " is out of range of ", m_info->usedSignatures.size(), " in module '", moduleString, "' field '", fieldString, "'");
173 kindIndex = m_info->importFunctionSignatureIndices.size();
174 SignatureIndex signatureIndex = SignatureInformation::get(m_info->usedSignatures[functionSignatureIndex]);
175 m_info->importFunctionSignatureIndices.uncheckedAppend(signatureIndex);
178 case ExternalKind::Table: {
179 bool isImport = true;
180 PartialResult result = parseTableHelper(isImport);
181 if (UNLIKELY(!result))
182 return makeUnexpected(WTFMove(result.error()));
185 case ExternalKind::Memory: {
186 bool isImport = true;
187 PartialResult result = parseMemoryHelper(isImport);
188 if (UNLIKELY(!result))
189 return makeUnexpected(WTFMove(result.error()));
192 case ExternalKind::Global: {
194 WASM_FAIL_IF_HELPER_FAILS(parseGlobalType(global));
195 WASM_PARSER_FAIL_IF(global.mutability == Global::Mutable, "Mutable Globals aren't supported");
197 kindIndex = m_info->globals.size();
198 m_info->globals.uncheckedAppend(WTFMove(global));
203 m_info->imports.uncheckedAppend({ WTFMove(moduleString), WTFMove(fieldString), kind, kindIndex });
206 m_info->firstInternalGlobal = m_info->globals.size();
210 auto ModuleParser::parseFunction() -> PartialResult
213 WASM_PARSER_FAIL_IF(!parseVarUInt32(count), "can't get Function section's count");
214 WASM_PARSER_FAIL_IF(count > maxFunctions, "Function section's count is too big ", count, " maximum ", maxFunctions);
215 WASM_PARSER_FAIL_IF(!m_info->internalFunctionSignatureIndices.tryReserveCapacity(count), "can't allocate enough memory for ", count, " Function signatures");
216 WASM_PARSER_FAIL_IF(!m_info->functionLocationInBinary.tryReserveCapacity(count), "can't allocate enough memory for ", count, "Function locations");
218 for (uint32_t i = 0; i < count; ++i) {
220 WASM_PARSER_FAIL_IF(!parseVarUInt32(typeNumber), "can't get ", i, "th Function's type number");
221 WASM_PARSER_FAIL_IF(typeNumber >= m_info->usedSignatures.size(), i, "th Function type number is invalid ", typeNumber);
223 SignatureIndex signatureIndex = SignatureInformation::get(m_info->usedSignatures[typeNumber]);
224 // The Code section fixes up start and end.
227 m_info->internalFunctionSignatureIndices.uncheckedAppend(signatureIndex);
228 m_info->functionLocationInBinary.uncheckedAppend({ start, end });
234 auto ModuleParser::parseResizableLimits(uint32_t& initial, std::optional<uint32_t>& maximum) -> PartialResult
239 WASM_PARSER_FAIL_IF(!parseVarUInt1(flags), "can't parse resizable limits flags");
240 WASM_PARSER_FAIL_IF(!parseVarUInt32(initial), "can't parse resizable limits initial page count");
244 WASM_PARSER_FAIL_IF(!parseVarUInt32(maximumInt), "can't parse resizable limits maximum page count");
245 WASM_PARSER_FAIL_IF(initial > maximumInt, "resizable limits has a initial page count of ", initial, " which is greater than its maximum ", maximumInt);
246 maximum = maximumInt;
252 auto ModuleParser::parseTableHelper(bool isImport) -> PartialResult
254 WASM_PARSER_FAIL_IF(m_tableCount > 0, "Cannot have more than one Table for now");
259 WASM_PARSER_FAIL_IF(!parseInt7(type), "can't parse Table type");
260 WASM_PARSER_FAIL_IF(type != Wasm::Anyfunc, "Table type should be anyfunc, got ", type);
263 std::optional<uint32_t> maximum;
264 PartialResult limits = parseResizableLimits(initial, maximum);
265 if (UNLIKELY(!limits))
266 return makeUnexpected(WTFMove(limits.error()));
267 WASM_PARSER_FAIL_IF(initial > maxTableEntries, "Table's initial page count of ", initial, " is too big, maximum ", maxTableEntries);
269 ASSERT(!maximum || *maximum >= initial);
271 m_info->tableInformation = TableInformation(initial, maximum, isImport);
276 auto ModuleParser::parseTable() -> PartialResult
279 WASM_PARSER_FAIL_IF(!parseVarUInt32(count), "can't get Table's count");
280 WASM_PARSER_FAIL_IF(count > 1, "Table count of ", count, " is invalid, at most 1 is allowed for now");
285 bool isImport = false;
286 PartialResult result = parseTableHelper(isImport);
287 if (UNLIKELY(!result))
288 return makeUnexpected(WTFMove(result.error()));
293 auto ModuleParser::parseMemoryHelper(bool isImport) -> PartialResult
295 WASM_PARSER_FAIL_IF(m_memoryCount, "there can at most be one Memory section for now");
299 PageCount initialPageCount;
300 PageCount maximumPageCount;
303 std::optional<uint32_t> maximum;
304 PartialResult limits = parseResizableLimits(initial, maximum);
305 if (UNLIKELY(!limits))
306 return makeUnexpected(WTFMove(limits.error()));
307 ASSERT(!maximum || *maximum >= initial);
308 WASM_PARSER_FAIL_IF(!PageCount::isValid(initial), "Memory's initial page count of ", initial, " is invalid");
310 initialPageCount = PageCount(initial);
313 WASM_PARSER_FAIL_IF(!PageCount::isValid(*maximum), "Memory's maximum page count of ", *maximum, " is invalid");
314 maximumPageCount = PageCount(*maximum);
317 ASSERT(initialPageCount);
318 ASSERT(!maximumPageCount || maximumPageCount >= initialPageCount);
320 m_info->memory = MemoryInformation(initialPageCount, maximumPageCount, isImport);
324 auto ModuleParser::parseMemory() -> PartialResult
327 WASM_PARSER_FAIL_IF(!parseVarUInt1(count), "can't parse Memory section's count");
332 WASM_PARSER_FAIL_IF(count != 1, "Memory section has more than one memory, WebAssembly currently only allows zero or one");
334 bool isImport = false;
335 return parseMemoryHelper(isImport);
338 auto ModuleParser::parseGlobal() -> PartialResult
340 uint32_t globalCount;
341 WASM_PARSER_FAIL_IF(!parseVarUInt32(globalCount), "can't get Global section's count");
342 WASM_PARSER_FAIL_IF(globalCount > maxGlobals, "Global section's count is too big ", globalCount, " maximum ", maxGlobals);
343 size_t totalBytes = globalCount + m_info->firstInternalGlobal;
344 WASM_PARSER_FAIL_IF((static_cast<uint32_t>(totalBytes) < globalCount) || !m_info->globals.tryReserveCapacity(totalBytes), "can't allocate memory for ", totalBytes, " globals");
346 for (uint32_t globalIndex = 0; globalIndex < globalCount; ++globalIndex) {
350 WASM_FAIL_IF_HELPER_FAILS(parseGlobalType(global));
351 Type typeForInitOpcode;
352 WASM_FAIL_IF_HELPER_FAILS(parseInitExpr(initOpcode, global.initialBitsOrImportNumber, typeForInitOpcode));
353 if (initOpcode == GetGlobal)
354 global.initializationType = Global::FromGlobalImport;
356 global.initializationType = Global::FromExpression;
357 WASM_PARSER_FAIL_IF(typeForInitOpcode != global.type, "Global init_expr opcode of type ", typeForInitOpcode, " doesn't match global's type ", global.type);
359 m_info->globals.uncheckedAppend(WTFMove(global));
365 auto ModuleParser::parseExport() -> PartialResult
367 uint32_t exportCount;
368 WASM_PARSER_FAIL_IF(!parseVarUInt32(exportCount), "can't get Export section's count");
369 WASM_PARSER_FAIL_IF(exportCount > maxExports, "Export section's count is too big ", exportCount, " maximum ", maxExports);
370 WASM_PARSER_FAIL_IF(!m_info->exports.tryReserveCapacity(exportCount), "can't allocate enough memory for ", exportCount, " exports");
372 HashSet<String> exportNames;
373 for (uint32_t exportNumber = 0; exportNumber < exportCount; ++exportNumber) {
379 WASM_PARSER_FAIL_IF(!parseVarUInt32(fieldLen), "can't get ", exportNumber, "th Export's field name length");
380 WASM_PARSER_FAIL_IF(!consumeUTF8String(fieldString, fieldLen), "can't get ", exportNumber, "th Export's field name of length ", fieldLen);
381 String fieldName = String::fromUTF8(fieldString);
382 WASM_PARSER_FAIL_IF(exportNames.contains(fieldName), "duplicate export: '", fieldString, "'");
383 exportNames.add(fieldName);
385 WASM_PARSER_FAIL_IF(!parseExternalKind(kind), "can't get ", exportNumber, "th Export's kind, named '", fieldString, "'");
386 WASM_PARSER_FAIL_IF(!parseVarUInt32(kindIndex), "can't get ", exportNumber, "th Export's kind index, named '", fieldString, "'");
388 case ExternalKind::Function: {
389 WASM_PARSER_FAIL_IF(kindIndex >= m_info->functionIndexSpaceSize(), exportNumber, "th Export has invalid function number ", kindIndex, " it exceeds the function index space ", m_info->functionIndexSpaceSize(), ", named '", fieldString, "'");
392 case ExternalKind::Table: {
393 WASM_PARSER_FAIL_IF(kindIndex >= m_tableCount, "can't export Table ", kindIndex, " there are ", m_tableCount, " Tables");
396 case ExternalKind::Memory: {
397 WASM_PARSER_FAIL_IF(!m_info->memory, "can't export a non-existent Memory");
398 WASM_PARSER_FAIL_IF(kindIndex, "can't export Memory ", kindIndex, " only one Table is currently supported");
401 case ExternalKind::Global: {
402 WASM_PARSER_FAIL_IF(kindIndex >= m_info->globals.size(), exportNumber, "th Export has invalid global number ", kindIndex, " it exceeds the globals count ", m_info->globals.size(), ", named '", fieldString, "'");
403 WASM_PARSER_FAIL_IF(m_info->globals[kindIndex].mutability != Global::Immutable, exportNumber, "th Export isn't immutable, named '", fieldString, "'");
408 m_info->exports.uncheckedAppend({ WTFMove(fieldString), kind, kindIndex });
414 auto ModuleParser::parseStart() -> PartialResult
416 uint32_t startFunctionIndex;
417 WASM_PARSER_FAIL_IF(!parseVarUInt32(startFunctionIndex), "can't get Start index");
418 WASM_PARSER_FAIL_IF(startFunctionIndex >= m_info->functionIndexSpaceSize(), "Start index ", startFunctionIndex, " exceeds function index space ", m_info->functionIndexSpaceSize());
419 SignatureIndex signatureIndex = m_info->signatureIndexFromFunctionIndexSpace(startFunctionIndex);
420 const Signature& signature = SignatureInformation::get(signatureIndex);
421 WASM_PARSER_FAIL_IF(signature.argumentCount(), "Start function can't have arguments");
422 WASM_PARSER_FAIL_IF(signature.returnType() != Void, "Start function can't return a value");
423 m_info->startFunctionIndexSpace = startFunctionIndex;
427 auto ModuleParser::parseElement() -> PartialResult
429 uint32_t elementCount;
430 WASM_PARSER_FAIL_IF(!parseVarUInt32(elementCount), "can't get Element section's count");
431 WASM_PARSER_FAIL_IF(elementCount > maxTableEntries, "Element section's count is too big ", elementCount, " maximum ", maxTableEntries);
432 WASM_PARSER_FAIL_IF(!m_info->elements.tryReserveCapacity(elementCount), "can't allocate memory for ", elementCount, " Elements");
433 for (unsigned elementNum = 0; elementNum < elementCount; ++elementNum) {
435 uint64_t initExprBits;
439 WASM_PARSER_FAIL_IF(!parseVarUInt32(tableIndex), "can't get ", elementNum, "th Element table index");
440 WASM_PARSER_FAIL_IF(tableIndex >= m_tableCount, "Element section for Table ", tableIndex, " exceeds available Table ", m_tableCount);
442 WASM_FAIL_IF_HELPER_FAILS(parseInitExpr(initOpcode, initExprBits, initExprType));
443 WASM_PARSER_FAIL_IF(initExprType != I32, "Element init_expr must produce an i32");
444 WASM_PARSER_FAIL_IF(!parseVarUInt32(indexCount), "can't get ", elementNum, "th index count for Element section");
445 WASM_PARSER_FAIL_IF(indexCount == std::numeric_limits<uint32_t>::max(), "Element section's ", elementNum, "th index count is too big ", indexCount);
447 ASSERT(!!m_info->tableInformation);
449 Element element(makeI32InitExpr(initOpcode, initExprBits));
450 WASM_PARSER_FAIL_IF(!element.functionIndices.tryReserveCapacity(indexCount), "can't allocate memory for ", indexCount, " Element indices");
452 for (unsigned index = 0; index < indexCount; ++index) {
453 uint32_t functionIndex;
454 WASM_PARSER_FAIL_IF(!parseVarUInt32(functionIndex), "can't get Element section's ", elementNum, "th element's ", index, "th index");
455 WASM_PARSER_FAIL_IF(functionIndex >= m_info->functionIndexSpaceSize(), "Element section's ", elementNum, "th element's ", index, "th index is ", functionIndex, " which exceeds the function index space size of ", m_info->functionIndexSpaceSize());
457 element.functionIndices.uncheckedAppend(functionIndex);
460 m_info->elements.uncheckedAppend(WTFMove(element));
466 auto ModuleParser::parseCode() -> PartialResult
469 WASM_PARSER_FAIL_IF(!parseVarUInt32(count), "can't get Code section's count");
470 WASM_PARSER_FAIL_IF(count == std::numeric_limits<uint32_t>::max(), "Code section's count is too big ", count);
471 WASM_PARSER_FAIL_IF(count != m_info->functionLocationInBinary.size(), "Code section count ", count, " exceeds the declared number of functions ", m_info->functionLocationInBinary.size());
473 for (uint32_t i = 0; i < count; ++i) {
474 uint32_t functionSize;
475 WASM_PARSER_FAIL_IF(!parseVarUInt32(functionSize), "can't get ", i, "th Code function's size");
476 WASM_PARSER_FAIL_IF(functionSize > length(), "Code function's size ", functionSize, " exceeds the module's size ", length());
477 WASM_PARSER_FAIL_IF(functionSize > length() - m_offset, "Code function's size ", functionSize, " exceeds the module's remaining size", length() - m_offset);
478 WASM_PARSER_FAIL_IF(functionSize > maxFunctionSize, "Code function's size ", functionSize, " is too big");
480 m_info->functionLocationInBinary[i].start = m_offset;
481 m_info->functionLocationInBinary[i].end = m_offset + functionSize;
482 m_offset = m_info->functionLocationInBinary[i].end;
488 auto ModuleParser::parseInitExpr(uint8_t& opcode, uint64_t& bitsOrImportNumber, Type& resultType) -> PartialResult
490 WASM_PARSER_FAIL_IF(!parseUInt8(opcode), "can't get init_expr's opcode");
495 WASM_PARSER_FAIL_IF(!parseVarInt32(constant), "can't get constant value for init_expr's i32.const");
496 bitsOrImportNumber = static_cast<uint64_t>(constant);
503 WASM_PARSER_FAIL_IF(!parseVarInt64(constant), "can't get constant value for init_expr's i64.const");
504 bitsOrImportNumber = constant;
511 WASM_PARSER_FAIL_IF(!parseUInt32(constant), "can't get constant value for init_expr's f32.const");
512 bitsOrImportNumber = constant;
519 WASM_PARSER_FAIL_IF(!parseUInt64(constant), "can't get constant value for init_expr's f64.const");
520 bitsOrImportNumber = constant;
527 WASM_PARSER_FAIL_IF(!parseVarUInt32(index), "can't get get_global's index");
529 WASM_PARSER_FAIL_IF(index >= m_info->globals.size(), "get_global's index ", index, " exceeds the number of globals ", m_info->globals.size());
530 WASM_PARSER_FAIL_IF(index >= m_info->firstInternalGlobal, "get_global import kind index ", index, " exceeds the first internal global ", m_info->firstInternalGlobal);
532 ASSERT(m_info->globals[index].mutability == Global::Immutable);
533 resultType = m_info->globals[index].type;
534 bitsOrImportNumber = index;
539 WASM_PARSER_FAIL_IF(true, "unknown init_expr opcode ", opcode);
543 WASM_PARSER_FAIL_IF(!parseUInt8(endOpcode), "can't get init_expr's end opcode");
544 WASM_PARSER_FAIL_IF(endOpcode != OpType::End, "init_expr should end with end, ended with ", endOpcode);
549 auto ModuleParser::parseGlobalType(Global& global) -> PartialResult
552 WASM_PARSER_FAIL_IF(!parseValueType(global.type), "can't get Global's value type");
553 WASM_PARSER_FAIL_IF(!parseVarUInt1(mutability), "can't get Global type's mutability");
554 global.mutability = static_cast<Global::Mutability>(mutability);
558 auto ModuleParser::parseData() -> PartialResult
560 uint32_t segmentCount;
561 WASM_PARSER_FAIL_IF(!parseVarUInt32(segmentCount), "can't get Data section's count");
562 WASM_PARSER_FAIL_IF(segmentCount > maxDataSegments, "Data section's count is too big ", segmentCount, " maximum ", maxDataSegments);
563 WASM_PARSER_FAIL_IF(!m_info->data.tryReserveCapacity(segmentCount), "can't allocate enough memory for Data section's ", segmentCount, " segments");
565 for (uint32_t segmentNumber = 0; segmentNumber < segmentCount; ++segmentNumber) {
566 uint32_t memoryIndex;
567 uint64_t initExprBits;
569 uint32_t dataByteLength;
571 WASM_PARSER_FAIL_IF(!parseVarUInt32(memoryIndex), "can't get ", segmentNumber, "th Data segment's index");
572 WASM_PARSER_FAIL_IF(memoryIndex >= m_memoryCount, segmentNumber, "th Data segment has index ", memoryIndex, " which exceeds the number of Memories ", m_memoryCount);
574 WASM_FAIL_IF_HELPER_FAILS(parseInitExpr(initOpcode, initExprBits, initExprType));
575 WASM_PARSER_FAIL_IF(initExprType != I32, segmentNumber, "th Data segment's init_expr must produce an i32");
576 WASM_PARSER_FAIL_IF(!parseVarUInt32(dataByteLength), "can't get ", segmentNumber, "th Data segment's data byte length");
577 WASM_PARSER_FAIL_IF(dataByteLength > maxModuleSize, segmentNumber, "th Data segment's data byte length is too big ", dataByteLength, " maximum ", maxModuleSize);
579 Segment* segment = Segment::create(makeI32InitExpr(initOpcode, initExprBits), dataByteLength);
580 WASM_PARSER_FAIL_IF(!segment, "can't allocate enough memory for ", segmentNumber, "th Data segment of size ", dataByteLength);
581 m_info->data.uncheckedAppend(Segment::adoptPtr(segment));
582 for (uint32_t dataByte = 0; dataByte < dataByteLength; ++dataByte) {
584 WASM_PARSER_FAIL_IF(!parseUInt8(byte), "can't get ", dataByte, "th data byte from ", segmentNumber, "th Data segment");
585 segment->byte(dataByte) = byte;
591 auto ModuleParser::parseCustom(uint32_t sectionLength) -> PartialResult
593 const uint32_t customSectionStartOffset = m_offset;
595 CustomSection section;
596 uint32_t customSectionNumber = m_info->customSections.size() + 1;
598 WASM_PARSER_FAIL_IF(!m_info->customSections.tryReserveCapacity(customSectionNumber), "can't allocate enough memory for ", customSectionNumber, "th custom section");
599 WASM_PARSER_FAIL_IF(!parseVarUInt32(nameLen), "can't get ", customSectionNumber, "th custom section's name length");
600 WASM_PARSER_FAIL_IF(!consumeUTF8String(section.name, nameLen), "nameLen get ", customSectionNumber, "th custom section's name of length ", nameLen);
602 uint32_t payloadBytes = sectionLength - (m_offset - customSectionStartOffset);
603 WASM_PARSER_FAIL_IF(!section.payload.tryReserveCapacity(payloadBytes), "can't allocate enough memory for ", customSectionNumber, "th custom section's ", payloadBytes, " bytes");
604 for (uint32_t byteNumber = 0; byteNumber < payloadBytes; ++byteNumber) {
606 WASM_PARSER_FAIL_IF(!parseUInt8(byte), "can't get ", byteNumber, "th data byte from ", customSectionNumber, "th custom section");
607 section.payload.uncheckedAppend(byte);
610 Name nameName = { 'n', 'a', 'm', 'e' };
611 if (section.name == nameName) {
612 NameSectionParser nameSectionParser(section.payload.begin(), section.payload.size(), m_info);
613 if (auto nameSection = nameSectionParser.parse())
614 m_info->nameSection = WTFMove(*nameSection);
617 m_info->customSections.uncheckedAppend(WTFMove(section));
622 } } // namespace JSC::Wasm
624 #endif // ENABLE(WEBASSEMBLY)