1/*
2 * Copyright (C) 2016-2018 Apple Inc. All rights reserved.
3 * Copyright (C) 2018 Yusuke Suzuki <[email protected]>.
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
41namespace JSC { namespace Wasm {
42
43auto 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 Vector<Type> arguments;
61 WASM_PARSER_FAIL_IF(!arguments.tryReserveCapacity(argumentCount), "can't allocate enough memory for Type section's ", i, "th signature");
62
63 for (unsigned i = 0; i < argumentCount; ++i) {
64 Type argumentType;
65 WASM_PARSER_FAIL_IF(!parseValueType(argumentType), "can't get ", i, "th argument Type");
66 arguments.append(argumentType);
67 }
68
69 uint32_t returnCount;
70 WASM_PARSER_FAIL_IF(!parseVarUInt32(returnCount), "can't get ", i, "th Type's return count");
71 WASM_PARSER_FAIL_IF(returnCount > 1 && !Options::useWebAssemblyMultiValues(), "Signatures cannot have more than one result type yet.");
72
73 Vector<Type, 1> returnTypes;
74 WASM_PARSER_FAIL_IF(!returnTypes.tryReserveCapacity(argumentCount), "can't allocate enough memory for Type section's ", i, "th signature");
75 for (unsigned i = 0; i < returnCount; ++i) {
76 Type value;
77 WASM_PARSER_FAIL_IF(!parseValueType(value), "can't get ", i, "th Type's return value");
78 returnTypes.append(value);
79 }
80
81 RefPtr<Signature> signature = SignatureInformation::signatureFor(returnTypes, arguments);
82 WASM_PARSER_FAIL_IF(!signature, "can't allocate enough memory for Type section's ", i, "th signature");
83
84 m_info->usedSignatures.uncheckedAppend(signature.releaseNonNull());
85 }
86 return { };
87}
88
89auto SectionParser::parseImport() -> PartialResult
90{
91 uint32_t importCount;
92 WASM_PARSER_FAIL_IF(!parseVarUInt32(importCount), "can't get Import section's count");
93 WASM_PARSER_FAIL_IF(importCount > maxImports, "Import section's count is too big ", importCount, " maximum ", maxImports);
94 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.
95 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.
96 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.
97
98 for (uint32_t importNumber = 0; importNumber < importCount; ++importNumber) {
99 uint32_t moduleLen;
100 uint32_t fieldLen;
101 Name moduleString;
102 Name fieldString;
103 ExternalKind kind;
104 unsigned kindIndex { 0 };
105
106 WASM_PARSER_FAIL_IF(!parseVarUInt32(moduleLen), "can't get ", importNumber, "th Import's module name length");
107 WASM_PARSER_FAIL_IF(!consumeUTF8String(moduleString, moduleLen), "can't get ", importNumber, "th Import's module name of length ", moduleLen);
108
109 WASM_PARSER_FAIL_IF(!parseVarUInt32(fieldLen), "can't get ", importNumber, "th Import's field name length in module '", moduleString, "'");
110 WASM_PARSER_FAIL_IF(!consumeUTF8String(fieldString, fieldLen), "can't get ", importNumber, "th Import's field name of length ", moduleLen, " in module '", moduleString, "'");
111
112 WASM_PARSER_FAIL_IF(!parseExternalKind(kind), "can't get ", importNumber, "th Import's kind in module '", moduleString, "' field '", fieldString, "'");
113 switch (kind) {
114 case ExternalKind::Function: {
115 uint32_t functionSignatureIndex;
116 WASM_PARSER_FAIL_IF(!parseVarUInt32(functionSignatureIndex), "can't get ", importNumber, "th Import's function signature in module '", moduleString, "' field '", fieldString, "'");
117 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, "'");
118 kindIndex = m_info->importFunctionSignatureIndices.size();
119 SignatureIndex signatureIndex = SignatureInformation::get(m_info->usedSignatures[functionSignatureIndex]);
120 m_info->importFunctionSignatureIndices.uncheckedAppend(signatureIndex);
121 break;
122 }
123 case ExternalKind::Table: {
124 bool isImport = true;
125 kindIndex = m_info->tables.size();
126 PartialResult result = parseTableHelper(isImport);
127 if (UNLIKELY(!result))
128 return makeUnexpected(WTFMove(result.error()));
129 break;
130 }
131 case ExternalKind::Memory: {
132 bool isImport = true;
133 PartialResult result = parseMemoryHelper(isImport);
134 if (UNLIKELY(!result))
135 return makeUnexpected(WTFMove(result.error()));
136 break;
137 }
138 case ExternalKind::Global: {
139 Global global;
140 WASM_FAIL_IF_HELPER_FAILS(parseGlobalType(global));
141 WASM_PARSER_FAIL_IF(global.mutability == Global::Mutable, "Mutable Globals aren't supported");
142
143 kindIndex = m_info->globals.size();
144 m_info->globals.uncheckedAppend(WTFMove(global));
145 break;
146 }
147 }
148
149 m_info->imports.uncheckedAppend({ WTFMove(moduleString), WTFMove(fieldString), kind, kindIndex });
150 }
151
152 m_info->firstInternalGlobal = m_info->globals.size();
153 return { };
154}
155
156auto SectionParser::parseFunction() -> PartialResult
157{
158 uint32_t count;
159 WASM_PARSER_FAIL_IF(!parseVarUInt32(count), "can't get Function section's count");
160 WASM_PARSER_FAIL_IF(count > maxFunctions, "Function section's count is too big ", count, " maximum ", maxFunctions);
161 WASM_PARSER_FAIL_IF(!m_info->internalFunctionSignatureIndices.tryReserveCapacity(count), "can't allocate enough memory for ", count, " Function signatures");
162 WASM_PARSER_FAIL_IF(!m_info->functions.tryReserveCapacity(count), "can't allocate enough memory for ", count, "Function locations");
163
164 for (uint32_t i = 0; i < count; ++i) {
165 uint32_t typeNumber;
166 WASM_PARSER_FAIL_IF(!parseVarUInt32(typeNumber), "can't get ", i, "th Function's type number");
167 WASM_PARSER_FAIL_IF(typeNumber >= m_info->usedSignatures.size(), i, "th Function type number is invalid ", typeNumber);
168
169 SignatureIndex signatureIndex = SignatureInformation::get(m_info->usedSignatures[typeNumber]);
170 // The Code section fixes up start and end.
171 size_t start = 0;
172 size_t end = 0;
173 m_info->internalFunctionSignatureIndices.uncheckedAppend(signatureIndex);
174 m_info->functions.uncheckedAppend({ start, end, Vector<uint8_t>() });
175 }
176
177 return { };
178}
179
180auto SectionParser::parseResizableLimits(uint32_t& initial, Optional<uint32_t>& maximum) -> PartialResult
181{
182 ASSERT(!maximum);
183
184 uint8_t flags;
185 WASM_PARSER_FAIL_IF(!parseVarUInt1(flags), "can't parse resizable limits flags");
186 WASM_PARSER_FAIL_IF(!parseVarUInt32(initial), "can't parse resizable limits initial page count");
187
188 if (flags) {
189 uint32_t maximumInt;
190 WASM_PARSER_FAIL_IF(!parseVarUInt32(maximumInt), "can't parse resizable limits maximum page count");
191 WASM_PARSER_FAIL_IF(initial > maximumInt, "resizable limits has an initial page count of ", initial, " which is greater than its maximum ", maximumInt);
192 maximum = maximumInt;
193 }
194
195 return { };
196}
197
198auto SectionParser::parseTableHelper(bool isImport) -> PartialResult
199{
200 WASM_PARSER_FAIL_IF(m_info->tableCount() >= maxTables, "Table count of ", m_info->tableCount(), " is too big, maximum ", maxTables);
201
202 int8_t type;
203 WASM_PARSER_FAIL_IF(!parseInt7(type), "can't parse Table type");
204 WASM_PARSER_FAIL_IF(type != Wasm::Funcref && type != Wasm::Anyref, "Table type should be funcref or anyref, got ", type);
205
206 uint32_t initial;
207 Optional<uint32_t> maximum;
208 PartialResult limits = parseResizableLimits(initial, maximum);
209 if (UNLIKELY(!limits))
210 return makeUnexpected(WTFMove(limits.error()));
211 WASM_PARSER_FAIL_IF(initial > maxTableEntries, "Table's initial page count of ", initial, " is too big, maximum ", maxTableEntries);
212
213 ASSERT(!maximum || *maximum >= initial);
214
215 TableElementType tableType = type == Wasm::Funcref ? TableElementType::Funcref : TableElementType::Anyref;
216 m_info->tables.append(TableInformation(initial, maximum, isImport, tableType));
217
218 return { };
219}
220
221auto SectionParser::parseTable() -> PartialResult
222{
223 uint32_t count;
224 WASM_PARSER_FAIL_IF(!parseVarUInt32(count), "can't get Table's count");
225
226 for (unsigned i = 0; i < count; ++i) {
227 bool isImport = false;
228 PartialResult result = parseTableHelper(isImport);
229 if (UNLIKELY(!result))
230 return makeUnexpected(WTFMove(result.error()));
231 }
232
233 return { };
234}
235
236auto SectionParser::parseMemoryHelper(bool isImport) -> PartialResult
237{
238 WASM_PARSER_FAIL_IF(m_info->memoryCount(), "there can at most be one Memory section for now");
239
240 PageCount initialPageCount;
241 PageCount maximumPageCount;
242 {
243 uint32_t initial;
244 Optional<uint32_t> maximum;
245 PartialResult limits = parseResizableLimits(initial, maximum);
246 if (UNLIKELY(!limits))
247 return makeUnexpected(WTFMove(limits.error()));
248 ASSERT(!maximum || *maximum >= initial);
249 WASM_PARSER_FAIL_IF(!PageCount::isValid(initial), "Memory's initial page count of ", initial, " is invalid");
250
251 initialPageCount = PageCount(initial);
252
253 if (maximum) {
254 WASM_PARSER_FAIL_IF(!PageCount::isValid(*maximum), "Memory's maximum page count of ", *maximum, " is invalid");
255 maximumPageCount = PageCount(*maximum);
256 }
257 }
258 ASSERT(initialPageCount);
259 ASSERT(!maximumPageCount || maximumPageCount >= initialPageCount);
260
261 m_info->memory = MemoryInformation(initialPageCount, maximumPageCount, isImport);
262 return { };
263}
264
265auto SectionParser::parseMemory() -> PartialResult
266{
267 uint8_t count;
268 WASM_PARSER_FAIL_IF(!parseVarUInt1(count), "can't parse Memory section's count");
269
270 if (!count)
271 return { };
272
273 WASM_PARSER_FAIL_IF(count != 1, "Memory section has more than one memory, WebAssembly currently only allows zero or one");
274
275 bool isImport = false;
276 return parseMemoryHelper(isImport);
277}
278
279auto SectionParser::parseGlobal() -> PartialResult
280{
281 uint32_t globalCount;
282 WASM_PARSER_FAIL_IF(!parseVarUInt32(globalCount), "can't get Global section's count");
283 WASM_PARSER_FAIL_IF(globalCount > maxGlobals, "Global section's count is too big ", globalCount, " maximum ", maxGlobals);
284 size_t totalBytes = globalCount + m_info->firstInternalGlobal;
285 WASM_PARSER_FAIL_IF((static_cast<uint32_t>(totalBytes) < globalCount) || !m_info->globals.tryReserveCapacity(totalBytes), "can't allocate memory for ", totalBytes, " globals");
286
287 for (uint32_t globalIndex = 0; globalIndex < globalCount; ++globalIndex) {
288 Global global;
289 uint8_t initOpcode;
290
291 WASM_FAIL_IF_HELPER_FAILS(parseGlobalType(global));
292 Type typeForInitOpcode;
293 WASM_FAIL_IF_HELPER_FAILS(parseInitExpr(initOpcode, global.initialBitsOrImportNumber, typeForInitOpcode));
294 if (initOpcode == GetGlobal)
295 global.initializationType = Global::FromGlobalImport;
296 else if (initOpcode == RefFunc)
297 global.initializationType = Global::FromRefFunc;
298 else
299 global.initializationType = Global::FromExpression;
300 WASM_PARSER_FAIL_IF(!isSubtype(typeForInitOpcode, global.type), "Global init_expr opcode of type ", typeForInitOpcode, " doesn't match global's type ", global.type);
301
302 m_info->globals.uncheckedAppend(WTFMove(global));
303 }
304
305 return { };
306}
307
308auto SectionParser::parseExport() -> PartialResult
309{
310 uint32_t exportCount;
311 WASM_PARSER_FAIL_IF(!parseVarUInt32(exportCount), "can't get Export section's count");
312 WASM_PARSER_FAIL_IF(exportCount > maxExports, "Export section's count is too big ", exportCount, " maximum ", maxExports);
313 WASM_PARSER_FAIL_IF(!m_info->exports.tryReserveCapacity(exportCount), "can't allocate enough memory for ", exportCount, " exports");
314
315 HashSet<String> exportNames;
316 for (uint32_t exportNumber = 0; exportNumber < exportCount; ++exportNumber) {
317 uint32_t fieldLen;
318 Name fieldString;
319 ExternalKind kind;
320 unsigned kindIndex;
321
322 WASM_PARSER_FAIL_IF(!parseVarUInt32(fieldLen), "can't get ", exportNumber, "th Export's field name length");
323 WASM_PARSER_FAIL_IF(!consumeUTF8String(fieldString, fieldLen), "can't get ", exportNumber, "th Export's field name of length ", fieldLen);
324 String fieldName = String::fromUTF8(fieldString);
325 WASM_PARSER_FAIL_IF(exportNames.contains(fieldName), "duplicate export: '", fieldString, "'");
326 exportNames.add(fieldName);
327
328 WASM_PARSER_FAIL_IF(!parseExternalKind(kind), "can't get ", exportNumber, "th Export's kind, named '", fieldString, "'");
329 WASM_PARSER_FAIL_IF(!parseVarUInt32(kindIndex), "can't get ", exportNumber, "th Export's kind index, named '", fieldString, "'");
330 switch (kind) {
331 case ExternalKind::Function: {
332 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, "'");
333 break;
334 }
335 case ExternalKind::Table: {
336 WASM_PARSER_FAIL_IF(kindIndex >= m_info->tableCount(), "can't export Table ", kindIndex, " there are ", m_info->tableCount(), " Tables");
337 break;
338 }
339 case ExternalKind::Memory: {
340 WASM_PARSER_FAIL_IF(!m_info->memory, "can't export a non-existent Memory");
341 WASM_PARSER_FAIL_IF(kindIndex, "can't export Memory ", kindIndex, " only one Table is currently supported");
342 break;
343 }
344 case ExternalKind::Global: {
345 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, "'");
346 WASM_PARSER_FAIL_IF(m_info->globals[kindIndex].mutability != Global::Immutable, exportNumber, "th Export isn't immutable, named '", fieldString, "'");
347 break;
348 }
349 }
350
351 m_info->exports.uncheckedAppend({ WTFMove(fieldString), kind, kindIndex });
352 }
353
354 return { };
355}
356
357auto SectionParser::parseStart() -> PartialResult
358{
359 uint32_t startFunctionIndex;
360 WASM_PARSER_FAIL_IF(!parseVarUInt32(startFunctionIndex), "can't get Start index");
361 WASM_PARSER_FAIL_IF(startFunctionIndex >= m_info->functionIndexSpaceSize(), "Start index ", startFunctionIndex, " exceeds function index space ", m_info->functionIndexSpaceSize());
362 SignatureIndex signatureIndex = m_info->signatureIndexFromFunctionIndexSpace(startFunctionIndex);
363 const Signature& signature = SignatureInformation::get(signatureIndex);
364 WASM_PARSER_FAIL_IF(signature.argumentCount(), "Start function can't have arguments");
365 WASM_PARSER_FAIL_IF(!signature.returnsVoid(), "Start function can't return a value");
366 m_info->startFunctionIndexSpace = startFunctionIndex;
367 return { };
368}
369
370auto SectionParser::parseElement() -> PartialResult
371{
372 uint32_t elementCount;
373 WASM_PARSER_FAIL_IF(!parseVarUInt32(elementCount), "can't get Element section's count");
374 WASM_PARSER_FAIL_IF(elementCount > maxTableEntries, "Element section's count is too big ", elementCount, " maximum ", maxTableEntries);
375 WASM_PARSER_FAIL_IF(!m_info->elements.tryReserveCapacity(elementCount), "can't allocate memory for ", elementCount, " Elements");
376 for (unsigned elementNum = 0; elementNum < elementCount; ++elementNum) {
377 uint32_t tableIndex;
378 uint64_t initExprBits;
379 uint8_t initOpcode;
380 uint32_t indexCount;
381
382 uint8_t magic;
383 WASM_PARSER_FAIL_IF(!parseUInt8(magic) || (magic && magic != 2), "can't get ", elementNum, "th Element reserved byte, which should be either 0x00 or 0x02 followed by a table index");
384
385 if (magic == 2)
386 WASM_PARSER_FAIL_IF(!parseVarUInt32(tableIndex), "can't get ", elementNum, "th Element table index");
387 else
388 tableIndex = 0;
389
390 WASM_PARSER_FAIL_IF(tableIndex >= m_info->tableCount(), "Element section for Table ", tableIndex, " exceeds available Table ", m_info->tableCount());
391 WASM_PARSER_FAIL_IF(m_info->tables[tableIndex].type() != TableElementType::Funcref, "Table ", tableIndex, " must have type 'funcref' to have an element section");
392 Type initExprType;
393 WASM_FAIL_IF_HELPER_FAILS(parseInitExpr(initOpcode, initExprBits, initExprType));
394 WASM_PARSER_FAIL_IF(initExprType != I32, "Element init_expr must produce an i32");
395 WASM_PARSER_FAIL_IF(!parseVarUInt32(indexCount), "can't get ", elementNum, "th index count for Element section");
396 WASM_PARSER_FAIL_IF(indexCount == std::numeric_limits<uint32_t>::max(), "Element section's ", elementNum, "th index count is too big ", indexCount);
397
398 ASSERT(!!m_info->tables[tableIndex]);
399
400 Element element(tableIndex, makeI32InitExpr(initOpcode, initExprBits));
401 WASM_PARSER_FAIL_IF(!element.functionIndices.tryReserveCapacity(indexCount), "can't allocate memory for ", indexCount, " Element indices");
402
403 for (unsigned index = 0; index < indexCount; ++index) {
404 uint32_t functionIndex;
405 WASM_PARSER_FAIL_IF(!parseVarUInt32(functionIndex), "can't get Element section's ", elementNum, "th element's ", index, "th index");
406 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());
407
408 element.functionIndices.uncheckedAppend(functionIndex);
409 }
410
411 m_info->elements.uncheckedAppend(WTFMove(element));
412 }
413
414 return { };
415}
416
417auto SectionParser::parseCode() -> PartialResult
418{
419 // The Code section is handled specially in StreamingParser.
420 RELEASE_ASSERT_NOT_REACHED();
421 return { };
422}
423
424auto SectionParser::parseInitExpr(uint8_t& opcode, uint64_t& bitsOrImportNumber, Type& resultType) -> PartialResult
425{
426 WASM_PARSER_FAIL_IF(!parseUInt8(opcode), "can't get init_expr's opcode");
427
428 switch (opcode) {
429 case I32Const: {
430 int32_t constant;
431 WASM_PARSER_FAIL_IF(!parseVarInt32(constant), "can't get constant value for init_expr's i32.const");
432 bitsOrImportNumber = static_cast<uint64_t>(constant);
433 resultType = I32;
434 break;
435 }
436
437 case I64Const: {
438 int64_t constant;
439 WASM_PARSER_FAIL_IF(!parseVarInt64(constant), "can't get constant value for init_expr's i64.const");
440 bitsOrImportNumber = constant;
441 resultType = I64;
442 break;
443 }
444
445 case F32Const: {
446 uint32_t constant;
447 WASM_PARSER_FAIL_IF(!parseUInt32(constant), "can't get constant value for init_expr's f32.const");
448 bitsOrImportNumber = constant;
449 resultType = F32;
450 break;
451 }
452
453 case F64Const: {
454 uint64_t constant;
455 WASM_PARSER_FAIL_IF(!parseUInt64(constant), "can't get constant value for init_expr's f64.const");
456 bitsOrImportNumber = constant;
457 resultType = F64;
458 break;
459 }
460
461 case GetGlobal: {
462 uint32_t index;
463 WASM_PARSER_FAIL_IF(!parseVarUInt32(index), "can't get get_global's index");
464
465 WASM_PARSER_FAIL_IF(index >= m_info->globals.size(), "get_global's index ", index, " exceeds the number of globals ", m_info->globals.size());
466 WASM_PARSER_FAIL_IF(index >= m_info->firstInternalGlobal, "get_global import kind index ", index, " exceeds the first internal global ", m_info->firstInternalGlobal);
467
468 ASSERT(m_info->globals[index].mutability == Global::Immutable);
469 resultType = m_info->globals[index].type;
470 bitsOrImportNumber = index;
471 break;
472 }
473
474 case RefNull: {
475 resultType = Funcref;
476 bitsOrImportNumber = JSValue::encode(jsNull());
477 break;
478 }
479
480 case RefFunc: {
481 uint32_t index;
482 WASM_PARSER_FAIL_IF(!parseVarUInt32(index), "can't get ref.func index");
483 WASM_PARSER_FAIL_IF(index >= m_info->functions.size(), "ref.func index", index, " exceeds the number of functions ", m_info->functions.size());
484
485 resultType = Funcref;
486 bitsOrImportNumber = index;
487 break;
488 }
489
490 default:
491 WASM_PARSER_FAIL_IF(true, "unknown init_expr opcode ", opcode);
492 }
493
494 uint8_t endOpcode;
495 WASM_PARSER_FAIL_IF(!parseUInt8(endOpcode), "can't get init_expr's end opcode");
496 WASM_PARSER_FAIL_IF(endOpcode != OpType::End, "init_expr should end with end, ended with ", endOpcode);
497
498 return { };
499}
500
501auto SectionParser::parseGlobalType(Global& global) -> PartialResult
502{
503 uint8_t mutability;
504 WASM_PARSER_FAIL_IF(!parseValueType(global.type), "can't get Global's value type");
505 WASM_PARSER_FAIL_IF(!parseVarUInt1(mutability), "can't get Global type's mutability");
506 global.mutability = static_cast<Global::Mutability>(mutability);
507 return { };
508}
509
510auto SectionParser::parseData() -> PartialResult
511{
512 uint32_t segmentCount;
513 WASM_PARSER_FAIL_IF(!parseVarUInt32(segmentCount), "can't get Data section's count");
514 WASM_PARSER_FAIL_IF(segmentCount > maxDataSegments, "Data section's count is too big ", segmentCount, " maximum ", maxDataSegments);
515 WASM_PARSER_FAIL_IF(!m_info->data.tryReserveCapacity(segmentCount), "can't allocate enough memory for Data section's ", segmentCount, " segments");
516
517 for (uint32_t segmentNumber = 0; segmentNumber < segmentCount; ++segmentNumber) {
518 uint32_t memoryIndex;
519 uint64_t initExprBits;
520 uint8_t initOpcode;
521 uint32_t dataByteLength;
522
523 WASM_PARSER_FAIL_IF(!parseVarUInt32(memoryIndex), "can't get ", segmentNumber, "th Data segment's index");
524 WASM_PARSER_FAIL_IF(memoryIndex >= m_info->memoryCount(), segmentNumber, "th Data segment has index ", memoryIndex, " which exceeds the number of Memories ", m_info->memoryCount());
525 Type initExprType;
526 WASM_FAIL_IF_HELPER_FAILS(parseInitExpr(initOpcode, initExprBits, initExprType));
527 WASM_PARSER_FAIL_IF(initExprType != I32, segmentNumber, "th Data segment's init_expr must produce an i32");
528 WASM_PARSER_FAIL_IF(!parseVarUInt32(dataByteLength), "can't get ", segmentNumber, "th Data segment's data byte length");
529 WASM_PARSER_FAIL_IF(dataByteLength > maxModuleSize, segmentNumber, "th Data segment's data byte length is too big ", dataByteLength, " maximum ", maxModuleSize);
530
531 Segment* segment = Segment::create(makeI32InitExpr(initOpcode, initExprBits), dataByteLength);
532 WASM_PARSER_FAIL_IF(!segment, "can't allocate enough memory for ", segmentNumber, "th Data segment of size ", dataByteLength);
533 m_info->data.uncheckedAppend(Segment::adoptPtr(segment));
534 for (uint32_t dataByte = 0; dataByte < dataByteLength; ++dataByte) {
535 uint8_t byte;
536 WASM_PARSER_FAIL_IF(!parseUInt8(byte), "can't get ", dataByte, "th data byte from ", segmentNumber, "th Data segment");
537 segment->byte(dataByte) = byte;
538 }
539 }
540 return { };
541}
542
543auto SectionParser::parseCustom() -> PartialResult
544{
545 CustomSection section;
546 uint32_t customSectionNumber = m_info->customSections.size() + 1;
547 uint32_t nameLen;
548 WASM_PARSER_FAIL_IF(!m_info->customSections.tryReserveCapacity(customSectionNumber), "can't allocate enough memory for ", customSectionNumber, "th custom section");
549 WASM_PARSER_FAIL_IF(!parseVarUInt32(nameLen), "can't get ", customSectionNumber, "th custom section's name length");
550 WASM_PARSER_FAIL_IF(!consumeUTF8String(section.name, nameLen), "nameLen get ", customSectionNumber, "th custom section's name of length ", nameLen);
551
552 uint32_t payloadBytes = length() - m_offset;
553 WASM_PARSER_FAIL_IF(!section.payload.tryReserveCapacity(payloadBytes), "can't allocate enough memory for ", customSectionNumber, "th custom section's ", payloadBytes, " bytes");
554 for (uint32_t byteNumber = 0; byteNumber < payloadBytes; ++byteNumber) {
555 uint8_t byte;
556 WASM_PARSER_FAIL_IF(!parseUInt8(byte), "can't get ", byteNumber, "th data byte from ", customSectionNumber, "th custom section");
557 section.payload.uncheckedAppend(byte);
558 }
559
560 Name nameName = { 'n', 'a', 'm', 'e' };
561 if (section.name == nameName) {
562 NameSectionParser nameSectionParser(section.payload.begin(), section.payload.size(), m_info);
563 if (auto nameSection = nameSectionParser.parse())
564 m_info->nameSection = WTFMove(*nameSection);
565 }
566
567 m_info->customSections.uncheckedAppend(WTFMove(section));
568
569 return { };
570}
571
572} } // namespace JSC::Wasm
573
574#endif // ENABLE(WEBASSEMBLY)
575