Fix crashes due to mishandling custom sections.
[WebKit-https.git] / Source / JavaScriptCore / wasm / WasmModuleParser.cpp
1 /*
2  * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
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.
12  *
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.
24  */
25
26 #include "config.h"
27 #include "WasmModuleParser.h"
28
29 #if ENABLE(WEBASSEMBLY)
30
31 #include "IdentifierInlines.h"
32 #include "WasmMemoryInformation.h"
33 #include "WasmNameSectionParser.h"
34 #include "WasmOps.h"
35 #include "WasmSections.h"
36
37 namespace JSC { namespace Wasm {
38
39 ALWAYS_INLINE I32InitExpr makeI32InitExpr(uint8_t opcode, uint32_t bits)
40 {
41     RELEASE_ASSERT(opcode == I32Const || opcode == GetGlobal);
42     if (opcode == I32Const)
43         return I32InitExpr::constValue(bits);
44     return I32InitExpr::globalImport(bits);
45 }
46
47 auto ModuleParser::parse() -> Result
48 {
49     const size_t minSize = 8;
50     uint32_t versionNumber;
51
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);
57
58     // This is not really a known section.
59     Section previousKnownSection = Section::Begin;
60     while (m_offset < length()) {
61         uint8_t sectionByte;
62
63         WASM_PARSER_FAIL_IF(!parseUInt7(sectionByte), "can't get section byte");
64
65         Section section = Section::Custom;
66         WASM_PARSER_FAIL_IF(!decodeSection(sectionByte, section));
67         ASSERT(section != Section::Begin);
68
69         uint32_t sectionLength;
70         WASM_PARSER_FAIL_IF(!validateOrder(previousKnownSection, section), "invalid section order, ", previousKnownSection, " followed by ", section);
71         WASM_PARSER_FAIL_IF(!parseVarUInt32(sectionLength), "can't get ", section, " section's length");
72         WASM_PARSER_FAIL_IF(sectionLength > length() - m_offset, section, "section of size ", sectionLength, " would overflow Module's size");
73
74         auto end = m_offset + sectionLength;
75
76         switch (section) {
77 #define WASM_SECTION_PARSE(NAME, ID, DESCRIPTION)                   \
78         case Section::NAME: {                                       \
79             WASM_FAIL_IF_HELPER_FAILS(parse ## NAME());             \
80             break;                                                  \
81         }
82         FOR_EACH_KNOWN_WASM_SECTION(WASM_SECTION_PARSE)
83 #undef WASM_SECTION_PARSE
84
85         case Section::Custom: {
86             WASM_FAIL_IF_HELPER_FAILS(parseCustom(sectionLength));
87             break;
88         }
89
90         case Section::Begin: {
91             RELEASE_ASSERT_NOT_REACHED();
92             break;
93         }
94         }
95
96         WASM_PARSER_FAIL_IF(end != m_offset, "parsing ended before the end of ", section, " section");
97
98
99         if (isKnownSection(section))
100             previousKnownSection = section;
101     }
102
103     return { };
104 }
105
106 auto ModuleParser::parseType() -> PartialResult
107 {
108     uint32_t count;
109
110     WASM_PARSER_FAIL_IF(!parseVarUInt32(count), "can't get Type section's count");
111     WASM_PARSER_FAIL_IF(count > maxTypes, "Type section's count is too big ", count, " maximum ", maxTypes);
112     WASM_PARSER_FAIL_IF(!m_info->usedSignatures.tryReserveCapacity(count), "can't allocate enough memory for Type section's ", count, " entries");
113
114     for (uint32_t i = 0; i < count; ++i) {
115         int8_t type;
116         uint32_t argumentCount;
117         Vector<Type> argumentTypes;
118
119         WASM_PARSER_FAIL_IF(!parseInt7(type), "can't get ", i, "th Type's type");
120         WASM_PARSER_FAIL_IF(type != Func, i, "th Type is non-Func ", type);
121         WASM_PARSER_FAIL_IF(!parseVarUInt32(argumentCount), "can't get ", i, "th Type's argument count");
122         WASM_PARSER_FAIL_IF(argumentCount > maxFunctionParams, i, "th argument count is too big ", argumentCount, " maximum ", maxFunctionParams);
123         RefPtr<Signature> maybeSignature = Signature::tryCreate(argumentCount);
124         WASM_PARSER_FAIL_IF(!maybeSignature, "can't allocate enough memory for Type section's ", i, "th signature");
125         Ref<Signature> signature = maybeSignature.releaseNonNull();
126
127         for (unsigned i = 0; i < argumentCount; ++i) {
128             Type argumentType;
129             WASM_PARSER_FAIL_IF(!parseResultType(argumentType), "can't get ", i, "th argument Type");
130             signature->argument(i) = argumentType;
131         }
132
133         uint8_t returnCount;
134         WASM_PARSER_FAIL_IF(!parseVarUInt1(returnCount), "can't get ", i, "th Type's return count");
135         Type returnType;
136         if (returnCount) {
137             Type value;
138             WASM_PARSER_FAIL_IF(!parseValueType(value), "can't get ", i, "th Type's return value");
139             returnType = static_cast<Type>(value);
140         } else
141             returnType = Type::Void;
142         signature->returnType() = returnType;
143
144         std::pair<SignatureIndex, Ref<Signature>> result = SignatureInformation::adopt(WTFMove(signature));
145         m_info->usedSignatures.uncheckedAppend(WTFMove(result.second));
146     }
147     return { };
148 }
149
150 auto ModuleParser::parseImport() -> PartialResult
151 {
152     uint32_t importCount;
153     WASM_PARSER_FAIL_IF(!parseVarUInt32(importCount), "can't get Import section's count");
154     WASM_PARSER_FAIL_IF(importCount > maxImports, "Import section's count is too big ", importCount, " maximum ", maxImports);
155     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.
156     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.
157     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.
158
159     for (uint32_t importNumber = 0; importNumber < importCount; ++importNumber) {
160         uint32_t moduleLen;
161         uint32_t fieldLen;
162         Name moduleString;
163         Name fieldString;
164         ExternalKind kind;
165         unsigned kindIndex { 0 };
166
167         WASM_PARSER_FAIL_IF(!parseVarUInt32(moduleLen), "can't get ", importNumber, "th Import's module name length");
168         WASM_PARSER_FAIL_IF(!consumeUTF8String(moduleString, moduleLen), "can't get ", importNumber, "th Import's module name of length ", moduleLen);
169
170         WASM_PARSER_FAIL_IF(!parseVarUInt32(fieldLen), "can't get ", importNumber, "th Import's field name length in module '", moduleString, "'");
171         WASM_PARSER_FAIL_IF(!consumeUTF8String(fieldString, fieldLen), "can't get ", importNumber, "th Import's field name of length ", moduleLen, " in module '", moduleString, "'");
172
173         WASM_PARSER_FAIL_IF(!parseExternalKind(kind), "can't get ", importNumber, "th Import's kind in module '", moduleString, "' field '", fieldString, "'");
174         switch (kind) {
175         case ExternalKind::Function: {
176             uint32_t functionSignatureIndex;
177             WASM_PARSER_FAIL_IF(!parseVarUInt32(functionSignatureIndex), "can't get ", importNumber, "th Import's function signature in module '", moduleString, "' field '", fieldString, "'");
178             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, "'");
179             kindIndex = m_info->importFunctionSignatureIndices.size();
180             SignatureIndex signatureIndex = SignatureInformation::get(m_info->usedSignatures[functionSignatureIndex]);
181             m_info->importFunctionSignatureIndices.uncheckedAppend(signatureIndex);
182             break;
183         }
184         case ExternalKind::Table: {
185             bool isImport = true;
186             PartialResult result = parseTableHelper(isImport);
187             if (UNLIKELY(!result))
188                 return makeUnexpected(WTFMove(result.error()));
189             break;
190         }
191         case ExternalKind::Memory: {
192             bool isImport = true;
193             PartialResult result = parseMemoryHelper(isImport);
194             if (UNLIKELY(!result))
195                 return makeUnexpected(WTFMove(result.error()));
196             break;
197         }
198         case ExternalKind::Global: {
199             Global global;
200             WASM_FAIL_IF_HELPER_FAILS(parseGlobalType(global));
201             WASM_PARSER_FAIL_IF(global.mutability == Global::Mutable, "Mutable Globals aren't supported");
202
203             kindIndex = m_info->globals.size();
204             m_info->globals.uncheckedAppend(WTFMove(global));
205             break;
206         }
207         }
208
209         m_info->imports.uncheckedAppend({ WTFMove(moduleString), WTFMove(fieldString), kind, kindIndex });
210     }
211
212     m_info->firstInternalGlobal = m_info->globals.size();
213     return { };
214 }
215
216 auto ModuleParser::parseFunction() -> PartialResult
217 {
218     uint32_t count;
219     WASM_PARSER_FAIL_IF(!parseVarUInt32(count), "can't get Function section's count");
220     WASM_PARSER_FAIL_IF(count > maxFunctions, "Function section's count is too big ", count, " maximum ", maxFunctions);
221     WASM_PARSER_FAIL_IF(!m_info->internalFunctionSignatureIndices.tryReserveCapacity(count), "can't allocate enough memory for ", count, " Function signatures");
222     WASM_PARSER_FAIL_IF(!m_info->functionLocationInBinary.tryReserveCapacity(count), "can't allocate enough memory for ", count, "Function locations");
223
224     for (uint32_t i = 0; i < count; ++i) {
225         uint32_t typeNumber;
226         WASM_PARSER_FAIL_IF(!parseVarUInt32(typeNumber), "can't get ", i, "th Function's type number");
227         WASM_PARSER_FAIL_IF(typeNumber >= m_info->usedSignatures.size(), i, "th Function type number is invalid ", typeNumber);
228
229         SignatureIndex signatureIndex = SignatureInformation::get(m_info->usedSignatures[typeNumber]);
230         // The Code section fixes up start and end.
231         size_t start = 0;
232         size_t end = 0;
233         m_info->internalFunctionSignatureIndices.uncheckedAppend(signatureIndex);
234         m_info->functionLocationInBinary.uncheckedAppend({ start, end });
235     }
236
237     return { };
238 }
239
240 auto ModuleParser::parseResizableLimits(uint32_t& initial, std::optional<uint32_t>& maximum) -> PartialResult
241 {
242     ASSERT(!maximum);
243
244     uint8_t flags;
245     WASM_PARSER_FAIL_IF(!parseVarUInt1(flags), "can't parse resizable limits flags");
246     WASM_PARSER_FAIL_IF(!parseVarUInt32(initial), "can't parse resizable limits initial page count");
247
248     if (flags) {
249         uint32_t maximumInt;
250         WASM_PARSER_FAIL_IF(!parseVarUInt32(maximumInt), "can't parse resizable limits maximum page count");
251         WASM_PARSER_FAIL_IF(initial > maximumInt, "resizable limits has a initial page count of ", initial, " which is greater than its maximum ", maximumInt);
252         maximum = maximumInt;
253     }
254
255     return { };
256 }
257
258 auto ModuleParser::parseTableHelper(bool isImport) -> PartialResult
259 {
260     WASM_PARSER_FAIL_IF(m_tableCount > 0, "Cannot have more than one Table for now");
261
262     ++m_tableCount;
263
264     int8_t type;
265     WASM_PARSER_FAIL_IF(!parseInt7(type), "can't parse Table type");
266     WASM_PARSER_FAIL_IF(type != Wasm::Anyfunc, "Table type should be anyfunc, got ", type);
267
268     uint32_t initial;
269     std::optional<uint32_t> maximum;
270     PartialResult limits = parseResizableLimits(initial, maximum);
271     if (UNLIKELY(!limits))
272         return makeUnexpected(WTFMove(limits.error()));
273     WASM_PARSER_FAIL_IF(initial > maxTableEntries, "Table's initial page count of ", initial, " is too big, maximum ", maxTableEntries);
274
275     ASSERT(!maximum || *maximum >= initial);
276
277     m_info->tableInformation = TableInformation(initial, maximum, isImport);
278
279     return { };
280 }
281
282 auto ModuleParser::parseTable() -> PartialResult
283 {
284     uint32_t count;
285     WASM_PARSER_FAIL_IF(!parseVarUInt32(count), "can't get Table's count");
286     WASM_PARSER_FAIL_IF(count > 1, "Table count of ", count, " is invalid, at most 1 is allowed for now");
287
288     if (!count)
289         return { };
290
291     bool isImport = false;
292     PartialResult result = parseTableHelper(isImport);
293     if (UNLIKELY(!result))
294         return makeUnexpected(WTFMove(result.error()));
295
296     return { };
297 }
298
299 auto ModuleParser::parseMemoryHelper(bool isImport) -> PartialResult
300 {
301     WASM_PARSER_FAIL_IF(m_memoryCount, "there can at most be one Memory section for now");
302
303     ++m_memoryCount;
304
305     PageCount initialPageCount;
306     PageCount maximumPageCount;
307     {
308         uint32_t initial;
309         std::optional<uint32_t> maximum;
310         PartialResult limits = parseResizableLimits(initial, maximum);
311         if (UNLIKELY(!limits))
312             return makeUnexpected(WTFMove(limits.error()));
313         ASSERT(!maximum || *maximum >= initial);
314         WASM_PARSER_FAIL_IF(!PageCount::isValid(initial), "Memory's initial page count of ", initial, " is invalid");
315
316         initialPageCount = PageCount(initial);
317
318         if (maximum) {
319             WASM_PARSER_FAIL_IF(!PageCount::isValid(*maximum), "Memory's maximum page count of ", *maximum, " is invalid");
320             maximumPageCount = PageCount(*maximum);
321         }
322     }
323     ASSERT(initialPageCount);
324     ASSERT(!maximumPageCount || maximumPageCount >= initialPageCount);
325
326     m_info->memory = MemoryInformation(initialPageCount, maximumPageCount, isImport);
327     return { };
328 }
329
330 auto ModuleParser::parseMemory() -> PartialResult
331 {
332     uint8_t count;
333     WASM_PARSER_FAIL_IF(!parseVarUInt1(count), "can't parse Memory section's count");
334
335     if (!count)
336         return { };
337
338     WASM_PARSER_FAIL_IF(count != 1, "Memory section has more than one memory, WebAssembly currently only allows zero or one");
339
340     bool isImport = false;
341     return parseMemoryHelper(isImport);
342 }
343
344 auto ModuleParser::parseGlobal() -> PartialResult
345 {
346     uint32_t globalCount;
347     WASM_PARSER_FAIL_IF(!parseVarUInt32(globalCount), "can't get Global section's count");
348     WASM_PARSER_FAIL_IF(globalCount > maxGlobals, "Global section's count is too big ", globalCount, " maximum ", maxGlobals);
349     size_t totalBytes = globalCount + m_info->firstInternalGlobal;
350     WASM_PARSER_FAIL_IF((static_cast<uint32_t>(totalBytes) < globalCount) || !m_info->globals.tryReserveCapacity(totalBytes), "can't allocate memory for ", totalBytes, " globals");
351
352     for (uint32_t globalIndex = 0; globalIndex < globalCount; ++globalIndex) {
353         Global global;
354         uint8_t initOpcode;
355
356         WASM_FAIL_IF_HELPER_FAILS(parseGlobalType(global));
357         Type typeForInitOpcode;
358         WASM_FAIL_IF_HELPER_FAILS(parseInitExpr(initOpcode, global.initialBitsOrImportNumber, typeForInitOpcode));
359         if (initOpcode == GetGlobal)
360             global.initializationType = Global::FromGlobalImport;
361         else
362             global.initializationType = Global::FromExpression;
363         WASM_PARSER_FAIL_IF(typeForInitOpcode != global.type, "Global init_expr opcode of type ", typeForInitOpcode, " doesn't match global's type ", global.type);
364
365         m_info->globals.uncheckedAppend(WTFMove(global));
366     }
367
368     return { };
369 }
370
371 auto ModuleParser::parseExport() -> PartialResult
372 {
373     uint32_t exportCount;
374     WASM_PARSER_FAIL_IF(!parseVarUInt32(exportCount), "can't get Export section's count");
375     WASM_PARSER_FAIL_IF(exportCount > maxExports, "Export section's count is too big ", exportCount, " maximum ", maxExports);
376     WASM_PARSER_FAIL_IF(!m_info->exports.tryReserveCapacity(exportCount), "can't allocate enough memory for ", exportCount, " exports");
377
378     HashSet<String> exportNames;
379     for (uint32_t exportNumber = 0; exportNumber < exportCount; ++exportNumber) {
380         uint32_t fieldLen;
381         Name fieldString;
382         ExternalKind kind;
383         unsigned kindIndex;
384
385         WASM_PARSER_FAIL_IF(!parseVarUInt32(fieldLen), "can't get ", exportNumber, "th Export's field name length");
386         WASM_PARSER_FAIL_IF(!consumeUTF8String(fieldString, fieldLen), "can't get ", exportNumber, "th Export's field name of length ", fieldLen);
387         String fieldName = String::fromUTF8(fieldString);
388         WASM_PARSER_FAIL_IF(exportNames.contains(fieldName), "duplicate export: '", fieldString, "'");
389         exportNames.add(fieldName);
390
391         WASM_PARSER_FAIL_IF(!parseExternalKind(kind), "can't get ", exportNumber, "th Export's kind, named '", fieldString, "'");
392         WASM_PARSER_FAIL_IF(!parseVarUInt32(kindIndex), "can't get ", exportNumber, "th Export's kind index, named '", fieldString, "'");
393         switch (kind) {
394         case ExternalKind::Function: {
395             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, "'");
396             break;
397         }
398         case ExternalKind::Table: {
399             WASM_PARSER_FAIL_IF(kindIndex >= m_tableCount, "can't export Table ", kindIndex, " there are ", m_tableCount, " Tables");
400             break;
401         }
402         case ExternalKind::Memory: {
403             WASM_PARSER_FAIL_IF(!m_info->memory, "can't export a non-existent Memory");
404             WASM_PARSER_FAIL_IF(kindIndex, "can't export Memory ", kindIndex, " only one Table is currently supported");
405             break;
406         }
407         case ExternalKind::Global: {
408             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, "'");
409             WASM_PARSER_FAIL_IF(m_info->globals[kindIndex].mutability != Global::Immutable, exportNumber, "th Export isn't immutable, named '", fieldString, "'");
410             break;
411         }
412         }
413
414         m_info->exports.uncheckedAppend({ WTFMove(fieldString), kind, kindIndex });
415     }
416
417     return { };
418 }
419
420 auto ModuleParser::parseStart() -> PartialResult
421 {
422     uint32_t startFunctionIndex;
423     WASM_PARSER_FAIL_IF(!parseVarUInt32(startFunctionIndex), "can't get Start index");
424     WASM_PARSER_FAIL_IF(startFunctionIndex >= m_info->functionIndexSpaceSize(), "Start index ", startFunctionIndex, " exceeds function index space ", m_info->functionIndexSpaceSize());
425     SignatureIndex signatureIndex = m_info->signatureIndexFromFunctionIndexSpace(startFunctionIndex);
426     const Signature& signature = SignatureInformation::get(signatureIndex);
427     WASM_PARSER_FAIL_IF(signature.argumentCount(), "Start function can't have arguments");
428     WASM_PARSER_FAIL_IF(signature.returnType() != Void, "Start function can't return a value");
429     m_info->startFunctionIndexSpace = startFunctionIndex;
430     return { };
431 }
432
433 auto ModuleParser::parseElement() -> PartialResult
434 {
435     uint32_t elementCount;
436     WASM_PARSER_FAIL_IF(!parseVarUInt32(elementCount), "can't get Element section's count");
437     WASM_PARSER_FAIL_IF(elementCount > maxTableEntries, "Element section's count is too big ", elementCount, " maximum ", maxTableEntries);
438     WASM_PARSER_FAIL_IF(!m_info->elements.tryReserveCapacity(elementCount), "can't allocate memory for ", elementCount, " Elements");
439     for (unsigned elementNum = 0; elementNum < elementCount; ++elementNum) {
440         uint32_t tableIndex;
441         uint64_t initExprBits;
442         uint8_t initOpcode;
443         uint32_t indexCount;
444
445         WASM_PARSER_FAIL_IF(!parseVarUInt32(tableIndex), "can't get ", elementNum, "th Element table index");
446         WASM_PARSER_FAIL_IF(tableIndex >= m_tableCount, "Element section for Table ", tableIndex, " exceeds available Table ", m_tableCount);
447         Type initExprType;
448         WASM_FAIL_IF_HELPER_FAILS(parseInitExpr(initOpcode, initExprBits, initExprType));
449         WASM_PARSER_FAIL_IF(initExprType != I32, "Element init_expr must produce an i32");
450         WASM_PARSER_FAIL_IF(!parseVarUInt32(indexCount), "can't get ", elementNum, "th index count for Element section");
451         WASM_PARSER_FAIL_IF(indexCount == std::numeric_limits<uint32_t>::max(), "Element section's ", elementNum, "th index count is too big ", indexCount);
452
453         ASSERT(!!m_info->tableInformation);
454
455         Element element(makeI32InitExpr(initOpcode, initExprBits));
456         WASM_PARSER_FAIL_IF(!element.functionIndices.tryReserveCapacity(indexCount), "can't allocate memory for ", indexCount, " Element indices");
457
458         for (unsigned index = 0; index < indexCount; ++index) {
459             uint32_t functionIndex;
460             WASM_PARSER_FAIL_IF(!parseVarUInt32(functionIndex), "can't get Element section's ", elementNum, "th element's ", index, "th index");
461             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());
462
463             element.functionIndices.uncheckedAppend(functionIndex);
464         }
465
466         m_info->elements.uncheckedAppend(WTFMove(element));
467     }
468
469     return { };
470 }
471
472 auto ModuleParser::parseCode() -> PartialResult
473 {
474     uint32_t count;
475     WASM_PARSER_FAIL_IF(!parseVarUInt32(count), "can't get Code section's count");
476     WASM_PARSER_FAIL_IF(count == std::numeric_limits<uint32_t>::max(), "Code section's count is too big ", count);
477     WASM_PARSER_FAIL_IF(count != m_info->functionLocationInBinary.size(), "Code section count ", count, " exceeds the declared number of functions ", m_info->functionLocationInBinary.size());
478
479     for (uint32_t i = 0; i < count; ++i) {
480         uint32_t functionSize;
481         WASM_PARSER_FAIL_IF(!parseVarUInt32(functionSize), "can't get ", i, "th Code function's size");
482         WASM_PARSER_FAIL_IF(functionSize > length(), "Code function's size ", functionSize, " exceeds the module's size ", length());
483         WASM_PARSER_FAIL_IF(functionSize > length() - m_offset, "Code function's size ", functionSize, " exceeds the module's remaining size", length() - m_offset);
484         WASM_PARSER_FAIL_IF(functionSize > maxFunctionSize, "Code function's size ", functionSize, " is too big");
485
486         m_info->functionLocationInBinary[i].start = m_offset;
487         m_info->functionLocationInBinary[i].end = m_offset + functionSize;
488         m_offset = m_info->functionLocationInBinary[i].end;
489     }
490
491     return { };
492 }
493
494 auto ModuleParser::parseInitExpr(uint8_t& opcode, uint64_t& bitsOrImportNumber, Type& resultType) -> PartialResult
495 {
496     WASM_PARSER_FAIL_IF(!parseUInt8(opcode), "can't get init_expr's opcode");
497
498     switch (opcode) {
499     case I32Const: {
500         int32_t constant;
501         WASM_PARSER_FAIL_IF(!parseVarInt32(constant), "can't get constant value for init_expr's i32.const");
502         bitsOrImportNumber = static_cast<uint64_t>(constant);
503         resultType = I32;
504         break;
505     }
506
507     case I64Const: {
508         int64_t constant;
509         WASM_PARSER_FAIL_IF(!parseVarInt64(constant), "can't get constant value for init_expr's i64.const");
510         bitsOrImportNumber = constant;
511         resultType = I64;
512         break;
513     }
514
515     case F32Const: {
516         uint32_t constant;
517         WASM_PARSER_FAIL_IF(!parseUInt32(constant), "can't get constant value for init_expr's f32.const");
518         bitsOrImportNumber = constant;
519         resultType = F32;
520         break;
521     }
522
523     case F64Const: {
524         uint64_t constant;
525         WASM_PARSER_FAIL_IF(!parseUInt64(constant), "can't get constant value for init_expr's f64.const");
526         bitsOrImportNumber = constant;
527         resultType = F64;
528         break;
529     }
530
531     case GetGlobal: {
532         uint32_t index;
533         WASM_PARSER_FAIL_IF(!parseVarUInt32(index), "can't get get_global's index");
534
535         WASM_PARSER_FAIL_IF(index >= m_info->globals.size(), "get_global's index ", index, " exceeds the number of globals ", m_info->globals.size());
536         WASM_PARSER_FAIL_IF(index >= m_info->firstInternalGlobal, "get_global import kind index ", index, " exceeds the first internal global ", m_info->firstInternalGlobal);
537
538         ASSERT(m_info->globals[index].mutability == Global::Immutable);
539         resultType = m_info->globals[index].type;
540         bitsOrImportNumber = index;
541         break;
542     }
543
544     default:
545         WASM_PARSER_FAIL_IF(true, "unknown init_expr opcode ", opcode);
546     }
547
548     uint8_t endOpcode;
549     WASM_PARSER_FAIL_IF(!parseUInt8(endOpcode), "can't get init_expr's end opcode");
550     WASM_PARSER_FAIL_IF(endOpcode != OpType::End, "init_expr should end with end, ended with ", endOpcode);
551
552     return { };
553 }
554
555 auto ModuleParser::parseGlobalType(Global& global) -> PartialResult
556 {
557     uint8_t mutability;
558     WASM_PARSER_FAIL_IF(!parseValueType(global.type), "can't get Global's value type");
559     WASM_PARSER_FAIL_IF(!parseVarUInt1(mutability), "can't get Global type's mutability");
560     global.mutability = static_cast<Global::Mutability>(mutability);
561     return { };
562 }
563
564 auto ModuleParser::parseData() -> PartialResult
565 {
566     uint32_t segmentCount;
567     WASM_PARSER_FAIL_IF(!parseVarUInt32(segmentCount), "can't get Data section's count");
568     WASM_PARSER_FAIL_IF(segmentCount > maxDataSegments, "Data section's count is too big ", segmentCount, " maximum ", maxDataSegments);
569     WASM_PARSER_FAIL_IF(!m_info->data.tryReserveCapacity(segmentCount), "can't allocate enough memory for Data section's ", segmentCount, " segments");
570
571     for (uint32_t segmentNumber = 0; segmentNumber < segmentCount; ++segmentNumber) {
572         uint32_t memoryIndex;
573         uint64_t initExprBits;
574         uint8_t initOpcode;
575         uint32_t dataByteLength;
576
577         WASM_PARSER_FAIL_IF(!parseVarUInt32(memoryIndex), "can't get ", segmentNumber, "th Data segment's index");
578         WASM_PARSER_FAIL_IF(memoryIndex >= m_memoryCount, segmentNumber, "th Data segment has index ", memoryIndex, " which exceeds the number of Memories ", m_memoryCount);
579         Type initExprType;
580         WASM_FAIL_IF_HELPER_FAILS(parseInitExpr(initOpcode, initExprBits, initExprType));
581         WASM_PARSER_FAIL_IF(initExprType != I32, segmentNumber, "th Data segment's init_expr must produce an i32");
582         WASM_PARSER_FAIL_IF(!parseVarUInt32(dataByteLength), "can't get ", segmentNumber, "th Data segment's data byte length");
583         WASM_PARSER_FAIL_IF(dataByteLength > maxModuleSize, segmentNumber, "th Data segment's data byte length is too big ", dataByteLength, " maximum ", maxModuleSize);
584
585         Segment* segment = Segment::create(makeI32InitExpr(initOpcode, initExprBits), dataByteLength);
586         WASM_PARSER_FAIL_IF(!segment, "can't allocate enough memory for ", segmentNumber, "th Data segment of size ", dataByteLength);
587         m_info->data.uncheckedAppend(Segment::adoptPtr(segment));
588         for (uint32_t dataByte = 0; dataByte < dataByteLength; ++dataByte) {
589             uint8_t byte;
590             WASM_PARSER_FAIL_IF(!parseUInt8(byte), "can't get ", dataByte, "th data byte from ", segmentNumber, "th Data segment");
591             segment->byte(dataByte) = byte;
592         }
593     }
594     return { };
595 }
596     
597 auto ModuleParser::parseCustom(uint32_t sectionLength) -> PartialResult
598 {
599     const uint32_t customSectionStartOffset = m_offset;
600
601     CustomSection section;
602     uint32_t customSectionNumber = m_info->customSections.size() + 1;
603     uint32_t nameLen;
604     WASM_PARSER_FAIL_IF(!m_info->customSections.tryReserveCapacity(customSectionNumber), "can't allocate enough memory for ", customSectionNumber, "th custom section");
605     WASM_PARSER_FAIL_IF(!parseVarUInt32(nameLen), "can't get ", customSectionNumber, "th custom section's name length");
606     WASM_PARSER_FAIL_IF(!consumeUTF8String(section.name, nameLen), "nameLen get ", customSectionNumber, "th custom section's name of length ", nameLen);
607
608     uint32_t payloadBytes = sectionLength - (m_offset - customSectionStartOffset);
609     WASM_PARSER_FAIL_IF(!section.payload.tryReserveCapacity(payloadBytes), "can't allocate enough memory for ", customSectionNumber, "th custom section's ", payloadBytes, " bytes");
610     for (uint32_t byteNumber = 0; byteNumber < payloadBytes; ++byteNumber) {
611         uint8_t byte;
612         WASM_PARSER_FAIL_IF(!parseUInt8(byte), "can't get ", byteNumber, "th data byte from ", customSectionNumber, "th custom section");
613         section.payload.uncheckedAppend(byte);
614     }
615
616     Name nameName = { 'n', 'a', 'm', 'e' };
617     if (section.name == nameName) {
618         NameSectionParser nameSectionParser(section.payload.begin(), section.payload.size(), m_info);
619         if (auto nameSection = nameSectionParser.parse())
620             m_info->nameSection = WTFMove(*nameSection);
621     }
622
623     m_info->customSections.uncheckedAppend(WTFMove(section));
624
625     return { };
626 }
627
628 } } // namespace JSC::Wasm
629
630 #endif // ENABLE(WEBASSEMBLY)