[WASM-References] Rename anyfunc to funcref
[WebKit-https.git] / Source / JavaScriptCore / wasm / WasmSectionParser.cpp
1 /*
2  * Copyright (C) 2016-2018 Apple Inc. All rights reserved.
3  * Copyright (C) 2018 Yusuke Suzuki <yusukesuzuki@slowstart.org>.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include "config.h"
28 #include "WasmSectionParser.h"
29
30 #if ENABLE(WEBASSEMBLY)
31
32 #include "IdentifierInlines.h"
33 #include "JSCJSValueInlines.h"
34 #include "WasmMemoryInformation.h"
35 #include "WasmNameSectionParser.h"
36 #include "WasmOps.h"
37 #include "WasmSections.h"
38 #include "WasmSignatureInlines.h"
39 #include <wtf/Optional.h>
40
41 namespace JSC { namespace Wasm {
42
43 auto SectionParser::parseType() -> PartialResult
44 {
45     uint32_t count;
46
47     WASM_PARSER_FAIL_IF(!parseVarUInt32(count), "can't get Type section's count");
48     WASM_PARSER_FAIL_IF(count > maxTypes, "Type section's count is too big ", count, " maximum ", maxTypes);
49     WASM_PARSER_FAIL_IF(!m_info->usedSignatures.tryReserveCapacity(count), "can't allocate enough memory for Type section's ", count, " entries");
50
51     for (uint32_t i = 0; i < count; ++i) {
52         int8_t type;
53         uint32_t argumentCount;
54         Vector<Type> argumentTypes;
55
56         WASM_PARSER_FAIL_IF(!parseInt7(type), "can't get ", i, "th Type's type");
57         WASM_PARSER_FAIL_IF(type != Func, i, "th Type is non-Func ", type);
58         WASM_PARSER_FAIL_IF(!parseVarUInt32(argumentCount), "can't get ", i, "th Type's argument count");
59         WASM_PARSER_FAIL_IF(argumentCount > maxFunctionParams, i, "th argument count is too big ", argumentCount, " maximum ", maxFunctionParams);
60         RefPtr<Signature> maybeSignature = Signature::tryCreate(argumentCount);
61         WASM_PARSER_FAIL_IF(!maybeSignature, "can't allocate enough memory for Type section's ", i, "th signature");
62         Ref<Signature> signature = maybeSignature.releaseNonNull();
63
64         for (unsigned i = 0; i < argumentCount; ++i) {
65             Type argumentType;
66             WASM_PARSER_FAIL_IF(!parseValueType(argumentType), "can't get ", i, "th argument Type");
67             signature->argument(i) = argumentType;
68         }
69
70         uint8_t returnCount;
71         WASM_PARSER_FAIL_IF(!parseVarUInt1(returnCount), "can't get ", i, "th Type's return count");
72         Type returnType;
73         if (returnCount) {
74             Type value;
75             WASM_PARSER_FAIL_IF(!parseValueType(value), "can't get ", i, "th Type's return value");
76             returnType = static_cast<Type>(value);
77         } else
78             returnType = Type::Void;
79         signature->returnType() = returnType;
80
81         m_info->usedSignatures.uncheckedAppend(SignatureInformation::adopt(WTFMove(signature)));
82     }
83     return { };
84 }
85
86 auto SectionParser::parseImport() -> PartialResult
87 {
88     uint32_t importCount;
89     WASM_PARSER_FAIL_IF(!parseVarUInt32(importCount), "can't get Import section's count");
90     WASM_PARSER_FAIL_IF(importCount > maxImports, "Import section's count is too big ", importCount, " maximum ", maxImports);
91     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.
92     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.
93     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.
94
95     for (uint32_t importNumber = 0; importNumber < importCount; ++importNumber) {
96         uint32_t moduleLen;
97         uint32_t fieldLen;
98         Name moduleString;
99         Name fieldString;
100         ExternalKind kind;
101         unsigned kindIndex { 0 };
102
103         WASM_PARSER_FAIL_IF(!parseVarUInt32(moduleLen), "can't get ", importNumber, "th Import's module name length");
104         WASM_PARSER_FAIL_IF(!consumeUTF8String(moduleString, moduleLen), "can't get ", importNumber, "th Import's module name of length ", moduleLen);
105
106         WASM_PARSER_FAIL_IF(!parseVarUInt32(fieldLen), "can't get ", importNumber, "th Import's field name length in module '", moduleString, "'");
107         WASM_PARSER_FAIL_IF(!consumeUTF8String(fieldString, fieldLen), "can't get ", importNumber, "th Import's field name of length ", moduleLen, " in module '", moduleString, "'");
108
109         WASM_PARSER_FAIL_IF(!parseExternalKind(kind), "can't get ", importNumber, "th Import's kind in module '", moduleString, "' field '", fieldString, "'");
110         switch (kind) {
111         case ExternalKind::Function: {
112             uint32_t functionSignatureIndex;
113             WASM_PARSER_FAIL_IF(!parseVarUInt32(functionSignatureIndex), "can't get ", importNumber, "th Import's function signature in module '", moduleString, "' field '", fieldString, "'");
114             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, "'");
115             kindIndex = m_info->importFunctionSignatureIndices.size();
116             SignatureIndex signatureIndex = SignatureInformation::get(m_info->usedSignatures[functionSignatureIndex]);
117             m_info->importFunctionSignatureIndices.uncheckedAppend(signatureIndex);
118             break;
119         }
120         case ExternalKind::Table: {
121             bool isImport = true;
122             kindIndex = m_info->tables.size();
123             PartialResult result = parseTableHelper(isImport);
124             if (UNLIKELY(!result))
125                 return makeUnexpected(WTFMove(result.error()));
126             break;
127         }
128         case ExternalKind::Memory: {
129             bool isImport = true;
130             PartialResult result = parseMemoryHelper(isImport);
131             if (UNLIKELY(!result))
132                 return makeUnexpected(WTFMove(result.error()));
133             break;
134         }
135         case ExternalKind::Global: {
136             Global global;
137             WASM_FAIL_IF_HELPER_FAILS(parseGlobalType(global));
138             WASM_PARSER_FAIL_IF(global.mutability == Global::Mutable, "Mutable Globals aren't supported");
139
140             kindIndex = m_info->globals.size();
141             m_info->globals.uncheckedAppend(WTFMove(global));
142             break;
143         }
144         }
145
146         m_info->imports.uncheckedAppend({ WTFMove(moduleString), WTFMove(fieldString), kind, kindIndex });
147     }
148
149     m_info->firstInternalGlobal = m_info->globals.size();
150     return { };
151 }
152
153 auto SectionParser::parseFunction() -> PartialResult
154 {
155     uint32_t count;
156     WASM_PARSER_FAIL_IF(!parseVarUInt32(count), "can't get Function section's count");
157     WASM_PARSER_FAIL_IF(count > maxFunctions, "Function section's count is too big ", count, " maximum ", maxFunctions);
158     WASM_PARSER_FAIL_IF(!m_info->internalFunctionSignatureIndices.tryReserveCapacity(count), "can't allocate enough memory for ", count, " Function signatures");
159     WASM_PARSER_FAIL_IF(!m_info->functions.tryReserveCapacity(count), "can't allocate enough memory for ", count, "Function locations");
160
161     for (uint32_t i = 0; i < count; ++i) {
162         uint32_t typeNumber;
163         WASM_PARSER_FAIL_IF(!parseVarUInt32(typeNumber), "can't get ", i, "th Function's type number");
164         WASM_PARSER_FAIL_IF(typeNumber >= m_info->usedSignatures.size(), i, "th Function type number is invalid ", typeNumber);
165
166         SignatureIndex signatureIndex = SignatureInformation::get(m_info->usedSignatures[typeNumber]);
167         // The Code section fixes up start and end.
168         size_t start = 0;
169         size_t end = 0;
170         m_info->internalFunctionSignatureIndices.uncheckedAppend(signatureIndex);
171         m_info->functions.uncheckedAppend({ start, end, Vector<uint8_t>() });
172     }
173
174     return { };
175 }
176
177 auto SectionParser::parseResizableLimits(uint32_t& initial, Optional<uint32_t>& maximum) -> PartialResult
178 {
179     ASSERT(!maximum);
180
181     uint8_t flags;
182     WASM_PARSER_FAIL_IF(!parseVarUInt1(flags), "can't parse resizable limits flags");
183     WASM_PARSER_FAIL_IF(!parseVarUInt32(initial), "can't parse resizable limits initial page count");
184
185     if (flags) {
186         uint32_t maximumInt;
187         WASM_PARSER_FAIL_IF(!parseVarUInt32(maximumInt), "can't parse resizable limits maximum page count");
188         WASM_PARSER_FAIL_IF(initial > maximumInt, "resizable limits has a initial page count of ", initial, " which is greater than its maximum ", maximumInt);
189         maximum = maximumInt;
190     }
191
192     return { };
193 }
194
195 auto SectionParser::parseTableHelper(bool isImport) -> PartialResult
196 {
197     WASM_PARSER_FAIL_IF(m_info->tableCount() >= maxTables, "Table count of ", m_info->tableCount(), " is too big, maximum ", maxTables);
198
199     int8_t type;
200     WASM_PARSER_FAIL_IF(!parseInt7(type), "can't parse Table type");
201     WASM_PARSER_FAIL_IF(type != Wasm::Funcref && type != Wasm::Anyref, "Table type should be funcref or anyref, got ", type);
202
203     uint32_t initial;
204     Optional<uint32_t> maximum;
205     PartialResult limits = parseResizableLimits(initial, maximum);
206     if (UNLIKELY(!limits))
207         return makeUnexpected(WTFMove(limits.error()));
208     WASM_PARSER_FAIL_IF(initial > maxTableEntries, "Table's initial page count of ", initial, " is too big, maximum ", maxTableEntries);
209
210     ASSERT(!maximum || *maximum >= initial);
211
212     TableElementType tableType = type == Wasm::Funcref ? TableElementType::Funcref : TableElementType::Anyref;
213     m_info->tables.append(TableInformation(initial, maximum, isImport, tableType));
214
215     return { };
216 }
217
218 auto SectionParser::parseTable() -> PartialResult
219 {
220     uint32_t count;
221     WASM_PARSER_FAIL_IF(!parseVarUInt32(count), "can't get Table's count");
222
223     for (unsigned i = 0; i < count; ++i) {
224         bool isImport = false;
225         PartialResult result = parseTableHelper(isImport);
226         if (UNLIKELY(!result))
227             return makeUnexpected(WTFMove(result.error()));
228     }
229
230     return { };
231 }
232
233 auto SectionParser::parseMemoryHelper(bool isImport) -> PartialResult
234 {
235     WASM_PARSER_FAIL_IF(m_info->memoryCount(), "there can at most be one Memory section for now");
236
237     PageCount initialPageCount;
238     PageCount maximumPageCount;
239     {
240         uint32_t initial;
241         Optional<uint32_t> maximum;
242         PartialResult limits = parseResizableLimits(initial, maximum);
243         if (UNLIKELY(!limits))
244             return makeUnexpected(WTFMove(limits.error()));
245         ASSERT(!maximum || *maximum >= initial);
246         WASM_PARSER_FAIL_IF(!PageCount::isValid(initial), "Memory's initial page count of ", initial, " is invalid");
247
248         initialPageCount = PageCount(initial);
249
250         if (maximum) {
251             WASM_PARSER_FAIL_IF(!PageCount::isValid(*maximum), "Memory's maximum page count of ", *maximum, " is invalid");
252             maximumPageCount = PageCount(*maximum);
253         }
254     }
255     ASSERT(initialPageCount);
256     ASSERT(!maximumPageCount || maximumPageCount >= initialPageCount);
257
258     m_info->memory = MemoryInformation(initialPageCount, maximumPageCount, isImport);
259     return { };
260 }
261
262 auto SectionParser::parseMemory() -> PartialResult
263 {
264     uint8_t count;
265     WASM_PARSER_FAIL_IF(!parseVarUInt1(count), "can't parse Memory section's count");
266
267     if (!count)
268         return { };
269
270     WASM_PARSER_FAIL_IF(count != 1, "Memory section has more than one memory, WebAssembly currently only allows zero or one");
271
272     bool isImport = false;
273     return parseMemoryHelper(isImport);
274 }
275
276 auto SectionParser::parseGlobal() -> PartialResult
277 {
278     uint32_t globalCount;
279     WASM_PARSER_FAIL_IF(!parseVarUInt32(globalCount), "can't get Global section's count");
280     WASM_PARSER_FAIL_IF(globalCount > maxGlobals, "Global section's count is too big ", globalCount, " maximum ", maxGlobals);
281     size_t totalBytes = globalCount + m_info->firstInternalGlobal;
282     WASM_PARSER_FAIL_IF((static_cast<uint32_t>(totalBytes) < globalCount) || !m_info->globals.tryReserveCapacity(totalBytes), "can't allocate memory for ", totalBytes, " globals");
283
284     for (uint32_t globalIndex = 0; globalIndex < globalCount; ++globalIndex) {
285         Global global;
286         uint8_t initOpcode;
287
288         WASM_FAIL_IF_HELPER_FAILS(parseGlobalType(global));
289         Type typeForInitOpcode;
290         WASM_FAIL_IF_HELPER_FAILS(parseInitExpr(initOpcode, global.initialBitsOrImportNumber, typeForInitOpcode));
291         if (initOpcode == GetGlobal)
292             global.initializationType = Global::FromGlobalImport;
293         else if (initOpcode == RefFunc)
294             global.initializationType = Global::FromRefFunc;
295         else
296             global.initializationType = Global::FromExpression;
297         WASM_PARSER_FAIL_IF(!isSubtype(typeForInitOpcode, global.type), "Global init_expr opcode of type ", typeForInitOpcode, " doesn't match global's type ", global.type);
298
299         m_info->globals.uncheckedAppend(WTFMove(global));
300     }
301
302     return { };
303 }
304
305 auto SectionParser::parseExport() -> PartialResult
306 {
307     uint32_t exportCount;
308     WASM_PARSER_FAIL_IF(!parseVarUInt32(exportCount), "can't get Export section's count");
309     WASM_PARSER_FAIL_IF(exportCount > maxExports, "Export section's count is too big ", exportCount, " maximum ", maxExports);
310     WASM_PARSER_FAIL_IF(!m_info->exports.tryReserveCapacity(exportCount), "can't allocate enough memory for ", exportCount, " exports");
311
312     HashSet<String> exportNames;
313     for (uint32_t exportNumber = 0; exportNumber < exportCount; ++exportNumber) {
314         uint32_t fieldLen;
315         Name fieldString;
316         ExternalKind kind;
317         unsigned kindIndex;
318
319         WASM_PARSER_FAIL_IF(!parseVarUInt32(fieldLen), "can't get ", exportNumber, "th Export's field name length");
320         WASM_PARSER_FAIL_IF(!consumeUTF8String(fieldString, fieldLen), "can't get ", exportNumber, "th Export's field name of length ", fieldLen);
321         String fieldName = String::fromUTF8(fieldString);
322         WASM_PARSER_FAIL_IF(exportNames.contains(fieldName), "duplicate export: '", fieldString, "'");
323         exportNames.add(fieldName);
324
325         WASM_PARSER_FAIL_IF(!parseExternalKind(kind), "can't get ", exportNumber, "th Export's kind, named '", fieldString, "'");
326         WASM_PARSER_FAIL_IF(!parseVarUInt32(kindIndex), "can't get ", exportNumber, "th Export's kind index, named '", fieldString, "'");
327         switch (kind) {
328         case ExternalKind::Function: {
329             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, "'");
330             break;
331         }
332         case ExternalKind::Table: {
333             WASM_PARSER_FAIL_IF(kindIndex >= m_info->tableCount(), "can't export Table ", kindIndex, " there are ", m_info->tableCount(), " Tables");
334             break;
335         }
336         case ExternalKind::Memory: {
337             WASM_PARSER_FAIL_IF(!m_info->memory, "can't export a non-existent Memory");
338             WASM_PARSER_FAIL_IF(kindIndex, "can't export Memory ", kindIndex, " only one Table is currently supported");
339             break;
340         }
341         case ExternalKind::Global: {
342             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, "'");
343             WASM_PARSER_FAIL_IF(m_info->globals[kindIndex].mutability != Global::Immutable, exportNumber, "th Export isn't immutable, named '", fieldString, "'");
344             break;
345         }
346         }
347
348         m_info->exports.uncheckedAppend({ WTFMove(fieldString), kind, kindIndex });
349     }
350
351     return { };
352 }
353
354 auto SectionParser::parseStart() -> PartialResult
355 {
356     uint32_t startFunctionIndex;
357     WASM_PARSER_FAIL_IF(!parseVarUInt32(startFunctionIndex), "can't get Start index");
358     WASM_PARSER_FAIL_IF(startFunctionIndex >= m_info->functionIndexSpaceSize(), "Start index ", startFunctionIndex, " exceeds function index space ", m_info->functionIndexSpaceSize());
359     SignatureIndex signatureIndex = m_info->signatureIndexFromFunctionIndexSpace(startFunctionIndex);
360     const Signature& signature = SignatureInformation::get(signatureIndex);
361     WASM_PARSER_FAIL_IF(signature.argumentCount(), "Start function can't have arguments");
362     WASM_PARSER_FAIL_IF(signature.returnType() != Void, "Start function can't return a value");
363     m_info->startFunctionIndexSpace = startFunctionIndex;
364     return { };
365 }
366
367 auto SectionParser::parseElement() -> PartialResult
368 {
369     uint32_t elementCount;
370     WASM_PARSER_FAIL_IF(!parseVarUInt32(elementCount), "can't get Element section's count");
371     WASM_PARSER_FAIL_IF(elementCount > maxTableEntries, "Element section's count is too big ", elementCount, " maximum ", maxTableEntries);
372     WASM_PARSER_FAIL_IF(!m_info->elements.tryReserveCapacity(elementCount), "can't allocate memory for ", elementCount, " Elements");
373     for (unsigned elementNum = 0; elementNum < elementCount; ++elementNum) {
374         uint32_t tableIndex;
375         uint64_t initExprBits;
376         uint8_t initOpcode;
377         uint32_t indexCount;
378
379         WASM_PARSER_FAIL_IF(!parseVarUInt32(tableIndex), "can't get ", elementNum, "th Element table index");
380         WASM_PARSER_FAIL_IF(tableIndex >= m_info->tableCount(), "Element section for Table ", tableIndex, " exceeds available Table ", m_info->tableCount());
381         WASM_PARSER_FAIL_IF(m_info->tables[tableIndex].type() != TableElementType::Funcref, "Table ", tableIndex, " must have type 'funcref' to have an element section");
382         Type initExprType;
383         WASM_FAIL_IF_HELPER_FAILS(parseInitExpr(initOpcode, initExprBits, initExprType));
384         WASM_PARSER_FAIL_IF(initExprType != I32, "Element init_expr must produce an i32");
385         WASM_PARSER_FAIL_IF(!parseVarUInt32(indexCount), "can't get ", elementNum, "th index count for Element section");
386         WASM_PARSER_FAIL_IF(indexCount == std::numeric_limits<uint32_t>::max(), "Element section's ", elementNum, "th index count is too big ", indexCount);
387
388         ASSERT(!!m_info->tables[tableIndex]);
389
390         Element element(tableIndex, makeI32InitExpr(initOpcode, initExprBits));
391         WASM_PARSER_FAIL_IF(!element.functionIndices.tryReserveCapacity(indexCount), "can't allocate memory for ", indexCount, " Element indices");
392
393         for (unsigned index = 0; index < indexCount; ++index) {
394             uint32_t functionIndex;
395             WASM_PARSER_FAIL_IF(!parseVarUInt32(functionIndex), "can't get Element section's ", elementNum, "th element's ", index, "th index");
396             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());
397
398             element.functionIndices.uncheckedAppend(functionIndex);
399         }
400
401         m_info->elements.uncheckedAppend(WTFMove(element));
402     }
403
404     return { };
405 }
406
407 // This function will be changed to be RELEASE_ASSERT_NOT_REACHED once we switch our parsing infrastructure to the streaming parser.
408 auto SectionParser::parseCode() -> PartialResult
409 {
410     uint32_t count;
411     WASM_PARSER_FAIL_IF(!parseVarUInt32(count), "can't get Code section's count");
412     WASM_PARSER_FAIL_IF(count == std::numeric_limits<uint32_t>::max(), "Code section's count is too big ", count);
413     WASM_PARSER_FAIL_IF(count != m_info->functions.size(), "Code section count ", count, " exceeds the declared number of functions ", m_info->functions.size());
414
415     for (uint32_t i = 0; i < count; ++i) {
416         uint32_t functionSize;
417         WASM_PARSER_FAIL_IF(!parseVarUInt32(functionSize), "can't get ", i, "th Code function's size");
418         WASM_PARSER_FAIL_IF(functionSize > length(), "Code function's size ", functionSize, " exceeds the module's size ", length());
419         WASM_PARSER_FAIL_IF(functionSize > length() - m_offset, "Code function's size ", functionSize, " exceeds the module's remaining size", length() - m_offset);
420         WASM_PARSER_FAIL_IF(functionSize > maxFunctionSize, "Code function's size ", functionSize, " is too big");
421
422         Vector<uint8_t> data(functionSize);
423         std::memcpy(data.data(), source() + m_offset, functionSize);
424         m_info->functions[i].start = m_offsetInSource + m_offset;
425         m_info->functions[i].end = m_offsetInSource + m_offset + functionSize;
426         m_info->functions[i].data = WTFMove(data);
427         m_offset += functionSize;
428     }
429
430     return { };
431 }
432
433 auto SectionParser::parseInitExpr(uint8_t& opcode, uint64_t& bitsOrImportNumber, Type& resultType) -> PartialResult
434 {
435     WASM_PARSER_FAIL_IF(!parseUInt8(opcode), "can't get init_expr's opcode");
436
437     switch (opcode) {
438     case I32Const: {
439         int32_t constant;
440         WASM_PARSER_FAIL_IF(!parseVarInt32(constant), "can't get constant value for init_expr's i32.const");
441         bitsOrImportNumber = static_cast<uint64_t>(constant);
442         resultType = I32;
443         break;
444     }
445
446     case I64Const: {
447         int64_t constant;
448         WASM_PARSER_FAIL_IF(!parseVarInt64(constant), "can't get constant value for init_expr's i64.const");
449         bitsOrImportNumber = constant;
450         resultType = I64;
451         break;
452     }
453
454     case F32Const: {
455         uint32_t constant;
456         WASM_PARSER_FAIL_IF(!parseUInt32(constant), "can't get constant value for init_expr's f32.const");
457         bitsOrImportNumber = constant;
458         resultType = F32;
459         break;
460     }
461
462     case F64Const: {
463         uint64_t constant;
464         WASM_PARSER_FAIL_IF(!parseUInt64(constant), "can't get constant value for init_expr's f64.const");
465         bitsOrImportNumber = constant;
466         resultType = F64;
467         break;
468     }
469
470     case GetGlobal: {
471         uint32_t index;
472         WASM_PARSER_FAIL_IF(!parseVarUInt32(index), "can't get get_global's index");
473
474         WASM_PARSER_FAIL_IF(index >= m_info->globals.size(), "get_global's index ", index, " exceeds the number of globals ", m_info->globals.size());
475         WASM_PARSER_FAIL_IF(index >= m_info->firstInternalGlobal, "get_global import kind index ", index, " exceeds the first internal global ", m_info->firstInternalGlobal);
476
477         ASSERT(m_info->globals[index].mutability == Global::Immutable);
478         resultType = m_info->globals[index].type;
479         bitsOrImportNumber = index;
480         break;
481     }
482
483     case RefNull: {
484         resultType = Funcref;
485         bitsOrImportNumber = JSValue::encode(jsNull());
486         break;
487     }
488
489     case RefFunc: {
490         uint32_t index;
491         WASM_PARSER_FAIL_IF(!parseVarUInt32(index), "can't get ref.func index");
492         WASM_PARSER_FAIL_IF(index >= m_info->functions.size(), "ref.func index", index, " exceeds the number of functions ", m_info->functions.size());
493
494         resultType = Funcref;
495         bitsOrImportNumber = index;
496         break;
497     }
498
499     default:
500         WASM_PARSER_FAIL_IF(true, "unknown init_expr opcode ", opcode);
501     }
502
503     uint8_t endOpcode;
504     WASM_PARSER_FAIL_IF(!parseUInt8(endOpcode), "can't get init_expr's end opcode");
505     WASM_PARSER_FAIL_IF(endOpcode != OpType::End, "init_expr should end with end, ended with ", endOpcode);
506
507     return { };
508 }
509
510 auto SectionParser::parseGlobalType(Global& global) -> PartialResult
511 {
512     uint8_t mutability;
513     WASM_PARSER_FAIL_IF(!parseValueType(global.type), "can't get Global's value type");
514     WASM_PARSER_FAIL_IF(!parseVarUInt1(mutability), "can't get Global type's mutability");
515     global.mutability = static_cast<Global::Mutability>(mutability);
516     return { };
517 }
518
519 auto SectionParser::parseData() -> PartialResult
520 {
521     uint32_t segmentCount;
522     WASM_PARSER_FAIL_IF(!parseVarUInt32(segmentCount), "can't get Data section's count");
523     WASM_PARSER_FAIL_IF(segmentCount > maxDataSegments, "Data section's count is too big ", segmentCount, " maximum ", maxDataSegments);
524     WASM_PARSER_FAIL_IF(!m_info->data.tryReserveCapacity(segmentCount), "can't allocate enough memory for Data section's ", segmentCount, " segments");
525
526     for (uint32_t segmentNumber = 0; segmentNumber < segmentCount; ++segmentNumber) {
527         uint32_t memoryIndex;
528         uint64_t initExprBits;
529         uint8_t initOpcode;
530         uint32_t dataByteLength;
531
532         WASM_PARSER_FAIL_IF(!parseVarUInt32(memoryIndex), "can't get ", segmentNumber, "th Data segment's index");
533         WASM_PARSER_FAIL_IF(memoryIndex >= m_info->memoryCount(), segmentNumber, "th Data segment has index ", memoryIndex, " which exceeds the number of Memories ", m_info->memoryCount());
534         Type initExprType;
535         WASM_FAIL_IF_HELPER_FAILS(parseInitExpr(initOpcode, initExprBits, initExprType));
536         WASM_PARSER_FAIL_IF(initExprType != I32, segmentNumber, "th Data segment's init_expr must produce an i32");
537         WASM_PARSER_FAIL_IF(!parseVarUInt32(dataByteLength), "can't get ", segmentNumber, "th Data segment's data byte length");
538         WASM_PARSER_FAIL_IF(dataByteLength > maxModuleSize, segmentNumber, "th Data segment's data byte length is too big ", dataByteLength, " maximum ", maxModuleSize);
539
540         Segment* segment = Segment::create(makeI32InitExpr(initOpcode, initExprBits), dataByteLength);
541         WASM_PARSER_FAIL_IF(!segment, "can't allocate enough memory for ", segmentNumber, "th Data segment of size ", dataByteLength);
542         m_info->data.uncheckedAppend(Segment::adoptPtr(segment));
543         for (uint32_t dataByte = 0; dataByte < dataByteLength; ++dataByte) {
544             uint8_t byte;
545             WASM_PARSER_FAIL_IF(!parseUInt8(byte), "can't get ", dataByte, "th data byte from ", segmentNumber, "th Data segment");
546             segment->byte(dataByte) = byte;
547         }
548     }
549     return { };
550 }
551
552 auto SectionParser::parseCustom() -> PartialResult
553 {
554     CustomSection section;
555     uint32_t customSectionNumber = m_info->customSections.size() + 1;
556     uint32_t nameLen;
557     WASM_PARSER_FAIL_IF(!m_info->customSections.tryReserveCapacity(customSectionNumber), "can't allocate enough memory for ", customSectionNumber, "th custom section");
558     WASM_PARSER_FAIL_IF(!parseVarUInt32(nameLen), "can't get ", customSectionNumber, "th custom section's name length");
559     WASM_PARSER_FAIL_IF(!consumeUTF8String(section.name, nameLen), "nameLen get ", customSectionNumber, "th custom section's name of length ", nameLen);
560
561     uint32_t payloadBytes = length() - m_offset;
562     WASM_PARSER_FAIL_IF(!section.payload.tryReserveCapacity(payloadBytes), "can't allocate enough memory for ", customSectionNumber, "th custom section's ", payloadBytes, " bytes");
563     for (uint32_t byteNumber = 0; byteNumber < payloadBytes; ++byteNumber) {
564         uint8_t byte;
565         WASM_PARSER_FAIL_IF(!parseUInt8(byte), "can't get ", byteNumber, "th data byte from ", customSectionNumber, "th custom section");
566         section.payload.uncheckedAppend(byte);
567     }
568
569     Name nameName = { 'n', 'a', 'm', 'e' };
570     if (section.name == nameName) {
571         NameSectionParser nameSectionParser(section.payload.begin(), section.payload.size(), m_info);
572         if (auto nameSection = nameSectionParser.parse())
573             m_info->nameSection = WTFMove(*nameSection);
574     }
575
576     m_info->customSections.uncheckedAppend(WTFMove(section));
577
578     return { };
579 }
580
581 } } // namespace JSC::Wasm
582
583 #endif // ENABLE(WEBASSEMBLY)