a098789fa00ea88e9322ffaa9808cd57ef2b6655
[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     Section previousSection = Section::Custom;
59     while (m_offset < length()) {
60         uint8_t sectionByte;
61
62         WASM_PARSER_FAIL_IF(!parseUInt7(sectionByte), "can't get section byte");
63
64         Section section = Section::Custom;
65         if (sectionByte) {
66             if (isValidSection(sectionByte))
67                 section = static_cast<Section>(sectionByte);
68         }
69
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");
74
75         auto end = m_offset + sectionLength;
76
77         switch (section) {
78 #define WASM_SECTION_PARSE(NAME, ID, DESCRIPTION)                   \
79         case Section::NAME: {                                       \
80             WASM_FAIL_IF_HELPER_FAILS(parse ## NAME());             \
81             break;                                                  \
82         }
83         FOR_EACH_WASM_SECTION(WASM_SECTION_PARSE)
84 #undef WASM_SECTION_PARSE
85
86         case Section::Custom: {
87             WASM_FAIL_IF_HELPER_FAILS(parseCustom(sectionLength));
88             break;
89         }
90         }
91
92         WASM_PARSER_FAIL_IF(end != m_offset, "parsing ended before the end of ", section, " section");
93
94         previousSection = section;
95     }
96
97     return { };
98 }
99
100 auto ModuleParser::parseType() -> PartialResult
101 {
102     uint32_t count;
103
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");
107
108     for (uint32_t i = 0; i < count; ++i) {
109         int8_t type;
110         uint32_t argumentCount;
111         Vector<Type> argumentTypes;
112
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();
120
121         for (unsigned i = 0; i < argumentCount; ++i) {
122             Type argumentType;
123             WASM_PARSER_FAIL_IF(!parseResultType(argumentType), "can't get ", i, "th argument Type");
124             signature->argument(i) = argumentType;
125         }
126
127         uint8_t returnCount;
128         WASM_PARSER_FAIL_IF(!parseVarUInt1(returnCount), "can't get ", i, "th Type's return count");
129         Type returnType;
130         if (returnCount) {
131             Type value;
132             WASM_PARSER_FAIL_IF(!parseValueType(value), "can't get ", i, "th Type's return value");
133             returnType = static_cast<Type>(value);
134         } else
135             returnType = Type::Void;
136         signature->returnType() = returnType;
137
138         std::pair<SignatureIndex, Ref<Signature>> result = SignatureInformation::adopt(WTFMove(signature));
139         m_info->usedSignatures.uncheckedAppend(WTFMove(result.second));
140     }
141     return { };
142 }
143
144 auto ModuleParser::parseImport() -> PartialResult
145 {
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.
152
153     for (uint32_t importNumber = 0; importNumber < importCount; ++importNumber) {
154         uint32_t moduleLen;
155         uint32_t fieldLen;
156         Name moduleString;
157         Name fieldString;
158         ExternalKind kind;
159         unsigned kindIndex { 0 };
160
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);
163
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, "'");
166
167         WASM_PARSER_FAIL_IF(!parseExternalKind(kind), "can't get ", importNumber, "th Import's kind in module '", moduleString, "' field '", fieldString, "'");
168         switch (kind) {
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);
176             break;
177         }
178         case ExternalKind::Table: {
179             bool isImport = true;
180             PartialResult result = parseTableHelper(isImport);
181             if (UNLIKELY(!result))
182                 return makeUnexpected(WTFMove(result.error()));
183             break;
184         }
185         case ExternalKind::Memory: {
186             bool isImport = true;
187             PartialResult result = parseMemoryHelper(isImport);
188             if (UNLIKELY(!result))
189                 return makeUnexpected(WTFMove(result.error()));
190             break;
191         }
192         case ExternalKind::Global: {
193             Global global;
194             WASM_FAIL_IF_HELPER_FAILS(parseGlobalType(global));
195             WASM_PARSER_FAIL_IF(global.mutability == Global::Mutable, "Mutable Globals aren't supported");
196
197             kindIndex = m_info->globals.size();
198             m_info->globals.uncheckedAppend(WTFMove(global));
199             break;
200         }
201         }
202
203         m_info->imports.uncheckedAppend({ WTFMove(moduleString), WTFMove(fieldString), kind, kindIndex });
204     }
205
206     m_info->firstInternalGlobal = m_info->globals.size();
207     return { };
208 }
209
210 auto ModuleParser::parseFunction() -> PartialResult
211 {
212     uint32_t count;
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");
217
218     for (uint32_t i = 0; i < count; ++i) {
219         uint32_t typeNumber;
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);
222
223         SignatureIndex signatureIndex = SignatureInformation::get(m_info->usedSignatures[typeNumber]);
224         // The Code section fixes up start and end.
225         size_t start = 0;
226         size_t end = 0;
227         m_info->internalFunctionSignatureIndices.uncheckedAppend(signatureIndex);
228         m_info->functionLocationInBinary.uncheckedAppend({ start, end });
229     }
230
231     return { };
232 }
233
234 auto ModuleParser::parseResizableLimits(uint32_t& initial, std::optional<uint32_t>& maximum) -> PartialResult
235 {
236     ASSERT(!maximum);
237
238     uint8_t flags;
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");
241
242     if (flags) {
243         uint32_t maximumInt;
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;
247     }
248
249     return { };
250 }
251
252 auto ModuleParser::parseTableHelper(bool isImport) -> PartialResult
253 {
254     WASM_PARSER_FAIL_IF(m_tableCount > 0, "Cannot have more than one Table for now");
255
256     ++m_tableCount;
257
258     int8_t type;
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);
261
262     uint32_t initial;
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);
268
269     ASSERT(!maximum || *maximum >= initial);
270
271     m_info->tableInformation = TableInformation(initial, maximum, isImport);
272
273     return { };
274 }
275
276 auto ModuleParser::parseTable() -> PartialResult
277 {
278     uint32_t count;
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");
281
282     if (!count)
283         return { };
284
285     bool isImport = false;
286     PartialResult result = parseTableHelper(isImport);
287     if (UNLIKELY(!result))
288         return makeUnexpected(WTFMove(result.error()));
289
290     return { };
291 }
292
293 auto ModuleParser::parseMemoryHelper(bool isImport) -> PartialResult
294 {
295     WASM_PARSER_FAIL_IF(m_memoryCount, "there can at most be one Memory section for now");
296
297     ++m_memoryCount;
298
299     PageCount initialPageCount;
300     PageCount maximumPageCount;
301     {
302         uint32_t initial;
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");
309
310         initialPageCount = PageCount(initial);
311
312         if (maximum) {
313             WASM_PARSER_FAIL_IF(!PageCount::isValid(*maximum), "Memory's maximum page count of ", *maximum, " is invalid");
314             maximumPageCount = PageCount(*maximum);
315         }
316     }
317     ASSERT(initialPageCount);
318     ASSERT(!maximumPageCount || maximumPageCount >= initialPageCount);
319
320     m_info->memory = MemoryInformation(initialPageCount, maximumPageCount, isImport);
321     return { };
322 }
323
324 auto ModuleParser::parseMemory() -> PartialResult
325 {
326     uint8_t count;
327     WASM_PARSER_FAIL_IF(!parseVarUInt1(count), "can't parse Memory section's count");
328
329     if (!count)
330         return { };
331
332     WASM_PARSER_FAIL_IF(count != 1, "Memory section has more than one memory, WebAssembly currently only allows zero or one");
333
334     bool isImport = false;
335     return parseMemoryHelper(isImport);
336 }
337
338 auto ModuleParser::parseGlobal() -> PartialResult
339 {
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");
345
346     for (uint32_t globalIndex = 0; globalIndex < globalCount; ++globalIndex) {
347         Global global;
348         uint8_t initOpcode;
349
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;
355         else
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);
358
359         m_info->globals.uncheckedAppend(WTFMove(global));
360     }
361
362     return { };
363 }
364
365 auto ModuleParser::parseExport() -> PartialResult
366 {
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");
371
372     HashSet<String> exportNames;
373     for (uint32_t exportNumber = 0; exportNumber < exportCount; ++exportNumber) {
374         uint32_t fieldLen;
375         Name fieldString;
376         ExternalKind kind;
377         unsigned kindIndex;
378
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);
384
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, "'");
387         switch (kind) {
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, "'");
390             break;
391         }
392         case ExternalKind::Table: {
393             WASM_PARSER_FAIL_IF(kindIndex >= m_tableCount, "can't export Table ", kindIndex, " there are ", m_tableCount, " Tables");
394             break;
395         }
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");
399             break;
400         }
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, "'");
404             break;
405         }
406         }
407
408         m_info->exports.uncheckedAppend({ WTFMove(fieldString), kind, kindIndex });
409     }
410
411     return { };
412 }
413
414 auto ModuleParser::parseStart() -> PartialResult
415 {
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;
424     return { };
425 }
426
427 auto ModuleParser::parseElement() -> PartialResult
428 {
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) {
434         uint32_t tableIndex;
435         uint64_t initExprBits;
436         uint8_t initOpcode;
437         uint32_t indexCount;
438
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);
441         Type initExprType;
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);
446
447         ASSERT(!!m_info->tableInformation);
448
449         Element element(makeI32InitExpr(initOpcode, initExprBits));
450         WASM_PARSER_FAIL_IF(!element.functionIndices.tryReserveCapacity(indexCount), "can't allocate memory for ", indexCount, " Element indices");
451
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());
456
457             element.functionIndices.uncheckedAppend(functionIndex);
458         }
459
460         m_info->elements.uncheckedAppend(WTFMove(element));
461     }
462
463     return { };
464 }
465
466 auto ModuleParser::parseCode() -> PartialResult
467 {
468     uint32_t count;
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());
472
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");
479
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;
483     }
484
485     return { };
486 }
487
488 auto ModuleParser::parseInitExpr(uint8_t& opcode, uint64_t& bitsOrImportNumber, Type& resultType) -> PartialResult
489 {
490     WASM_PARSER_FAIL_IF(!parseUInt8(opcode), "can't get init_expr's opcode");
491
492     switch (opcode) {
493     case I32Const: {
494         int32_t constant;
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);
497         resultType = I32;
498         break;
499     }
500
501     case I64Const: {
502         int64_t constant;
503         WASM_PARSER_FAIL_IF(!parseVarInt64(constant), "can't get constant value for init_expr's i64.const");
504         bitsOrImportNumber = constant;
505         resultType = I64;
506         break;
507     }
508
509     case F32Const: {
510         uint32_t constant;
511         WASM_PARSER_FAIL_IF(!parseUInt32(constant), "can't get constant value for init_expr's f32.const");
512         bitsOrImportNumber = constant;
513         resultType = F32;
514         break;
515     }
516
517     case F64Const: {
518         uint64_t constant;
519         WASM_PARSER_FAIL_IF(!parseUInt64(constant), "can't get constant value for init_expr's f64.const");
520         bitsOrImportNumber = constant;
521         resultType = F64;
522         break;
523     }
524
525     case GetGlobal: {
526         uint32_t index;
527         WASM_PARSER_FAIL_IF(!parseVarUInt32(index), "can't get get_global's index");
528
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);
531
532         ASSERT(m_info->globals[index].mutability == Global::Immutable);
533         resultType = m_info->globals[index].type;
534         bitsOrImportNumber = index;
535         break;
536     }
537
538     default:
539         WASM_PARSER_FAIL_IF(true, "unknown init_expr opcode ", opcode);
540     }
541
542     uint8_t endOpcode;
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);
545
546     return { };
547 }
548
549 auto ModuleParser::parseGlobalType(Global& global) -> PartialResult
550 {
551     uint8_t mutability;
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);
555     return { };
556 }
557
558 auto ModuleParser::parseData() -> PartialResult
559 {
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");
564
565     for (uint32_t segmentNumber = 0; segmentNumber < segmentCount; ++segmentNumber) {
566         uint32_t memoryIndex;
567         uint64_t initExprBits;
568         uint8_t initOpcode;
569         uint32_t dataByteLength;
570
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);
573         Type initExprType;
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);
578
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) {
583             uint8_t byte;
584             WASM_PARSER_FAIL_IF(!parseUInt8(byte), "can't get ", dataByte, "th data byte from ", segmentNumber, "th Data segment");
585             segment->byte(dataByte) = byte;
586         }
587     }
588     return { };
589 }
590     
591 auto ModuleParser::parseCustom(uint32_t sectionLength) -> PartialResult
592 {
593     const uint32_t customSectionStartOffset = m_offset;
594
595     CustomSection section;
596     uint32_t customSectionNumber = m_info->customSections.size() + 1;
597     uint32_t nameLen;
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);
601
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) {
605         uint8_t byte;
606         WASM_PARSER_FAIL_IF(!parseUInt8(byte), "can't get ", byteNumber, "th data byte from ", customSectionNumber, "th custom section");
607         section.payload.uncheckedAppend(byte);
608     }
609
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);
615     }
616
617     m_info->customSections.uncheckedAppend(WTFMove(section));
618
619     return { };
620 }
621
622 } } // namespace JSC::Wasm
623
624 #endif // ENABLE(WEBASSEMBLY)