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