Serenity Operating System
1/*
2 * Copyright (c) 2021, Ali Mohammad Pur <mpfard@serenityos.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <AK/Debug.h>
8#include <AK/Endian.h>
9#include <AK/LEB128.h>
10#include <AK/MemoryStream.h>
11#include <AK/ScopeGuard.h>
12#include <AK/ScopeLogger.h>
13#include <LibWasm/Types.h>
14
15namespace Wasm {
16
17ParseError with_eof_check(Stream const& stream, ParseError error_if_not_eof)
18{
19 if (stream.is_eof())
20 return ParseError::UnexpectedEof;
21 return error_if_not_eof;
22}
23
24template<typename T>
25static auto parse_vector(Stream& stream)
26{
27 ScopeLogger<WASM_BINPARSER_DEBUG> logger;
28 if constexpr (requires { T::parse(stream); }) {
29 using ResultT = typename decltype(T::parse(stream))::ValueType;
30 auto count_or_error = stream.read_value<LEB128<size_t>>();
31 if (count_or_error.is_error())
32 return ParseResult<Vector<ResultT>> { with_eof_check(stream, ParseError::ExpectedSize) };
33 size_t count = count_or_error.release_value();
34
35 Vector<ResultT> entries;
36 for (size_t i = 0; i < count; ++i) {
37 auto result = T::parse(stream);
38 if (result.is_error())
39 return ParseResult<Vector<ResultT>> { result.error() };
40 entries.append(result.release_value());
41 }
42 return ParseResult<Vector<ResultT>> { move(entries) };
43 } else {
44 auto count_or_error = stream.read_value<LEB128<size_t>>();
45 if (count_or_error.is_error())
46 return ParseResult<Vector<T>> { with_eof_check(stream, ParseError::ExpectedSize) };
47 size_t count = count_or_error.release_value();
48
49 Vector<T> entries;
50 for (size_t i = 0; i < count; ++i) {
51 if constexpr (IsSame<T, size_t>) {
52 auto value_or_error = stream.read_value<LEB128<size_t>>();
53 if (value_or_error.is_error())
54 return ParseResult<Vector<T>> { with_eof_check(stream, ParseError::ExpectedSize) };
55 size_t value = value_or_error.release_value();
56 entries.append(value);
57 } else if constexpr (IsSame<T, ssize_t>) {
58 auto value_or_error = stream.read_value<LEB128<ssize_t>>();
59 if (value_or_error.is_error())
60 return ParseResult<Vector<T>> { with_eof_check(stream, ParseError::ExpectedSize) };
61 ssize_t value = value_or_error.release_value();
62 entries.append(value);
63 } else if constexpr (IsSame<T, u8>) {
64 if (count > Constants::max_allowed_vector_size)
65 return ParseResult<Vector<T>> { ParseError::HugeAllocationRequested };
66 entries.resize(count);
67 if (stream.read_until_filled({ entries.data(), entries.size() }).is_error())
68 return ParseResult<Vector<T>> { with_eof_check(stream, ParseError::InvalidInput) };
69 break; // Note: We read this all in one go!
70 }
71 }
72 return ParseResult<Vector<T>> { move(entries) };
73 }
74}
75
76static ParseResult<DeprecatedString> parse_name(Stream& stream)
77{
78 ScopeLogger<WASM_BINPARSER_DEBUG> logger;
79 auto data = parse_vector<u8>(stream);
80 if (data.is_error())
81 return data.error();
82
83 return DeprecatedString::copy(data.value());
84}
85
86template<typename T>
87struct ParseUntilAnyOfResult {
88 u8 terminator { 0 };
89 Vector<T> values;
90};
91template<typename T, u8... terminators, typename... Args>
92static ParseResult<ParseUntilAnyOfResult<T>> parse_until_any_of(Stream& stream, Args&... args)
93requires(requires(Stream& stream, Args... args) { T::parse(stream, args...); })
94{
95 ScopeLogger<WASM_BINPARSER_DEBUG> logger;
96 ReconsumableStream new_stream { stream };
97
98 ParseUntilAnyOfResult<T> result;
99 for (;;) {
100 auto byte_or_error = new_stream.read_value<u8>();
101 if (byte_or_error.is_error())
102 return with_eof_check(stream, ParseError::ExpectedValueOrTerminator);
103
104 auto byte = byte_or_error.release_value();
105
106 constexpr auto equals = [](auto&& a, auto&& b) { return a == b; };
107
108 if ((... || equals(byte, terminators))) {
109 result.terminator = byte;
110 return result;
111 }
112
113 new_stream.unread({ &byte, 1 });
114 auto parse_result = T::parse(new_stream, args...);
115 if (parse_result.is_error())
116 return parse_result.error();
117
118 result.values.extend(parse_result.release_value());
119 }
120}
121
122ParseResult<ValueType> ValueType::parse(Stream& stream)
123{
124 ScopeLogger<WASM_BINPARSER_DEBUG> logger("ValueType"sv);
125 auto tag_or_error = stream.read_value<u8>();
126 if (tag_or_error.is_error())
127 return with_eof_check(stream, ParseError::ExpectedKindTag);
128
129 auto tag = tag_or_error.release_value();
130
131 switch (tag) {
132 case Constants::i32_tag:
133 return ValueType(I32);
134 case Constants::i64_tag:
135 return ValueType(I64);
136 case Constants::f32_tag:
137 return ValueType(F32);
138 case Constants::f64_tag:
139 return ValueType(F64);
140 case Constants::function_reference_tag:
141 return ValueType(FunctionReference);
142 case Constants::extern_reference_tag:
143 return ValueType(ExternReference);
144 default:
145 return with_eof_check(stream, ParseError::InvalidTag);
146 }
147}
148
149ParseResult<ResultType> ResultType::parse(Stream& stream)
150{
151 ScopeLogger<WASM_BINPARSER_DEBUG> logger("ResultType"sv);
152 auto types = parse_vector<ValueType>(stream);
153 if (types.is_error())
154 return types.error();
155 return ResultType { types.release_value() };
156}
157
158ParseResult<FunctionType> FunctionType::parse(Stream& stream)
159{
160 ScopeLogger<WASM_BINPARSER_DEBUG> logger("FunctionType"sv);
161 auto tag_or_error = stream.read_value<u8>();
162 if (tag_or_error.is_error())
163 return with_eof_check(stream, ParseError::ExpectedKindTag);
164
165 auto tag = tag_or_error.release_value();
166
167 if (tag != Constants::function_signature_tag) {
168 dbgln("Expected 0x60, but found {:#x}", tag);
169 return with_eof_check(stream, ParseError::InvalidTag);
170 }
171
172 auto parameters_result = parse_vector<ValueType>(stream);
173 if (parameters_result.is_error())
174 return parameters_result.error();
175 auto results_result = parse_vector<ValueType>(stream);
176 if (results_result.is_error())
177 return results_result.error();
178
179 return FunctionType { parameters_result.release_value(), results_result.release_value() };
180}
181
182ParseResult<Limits> Limits::parse(Stream& stream)
183{
184 ScopeLogger<WASM_BINPARSER_DEBUG> logger("Limits"sv);
185 auto flag_or_error = stream.read_value<u8>();
186 if (flag_or_error.is_error())
187 return with_eof_check(stream, ParseError::ExpectedKindTag);
188
189 auto flag = flag_or_error.release_value();
190
191 if (flag > 1)
192 return with_eof_check(stream, ParseError::InvalidTag);
193
194 auto min_or_error = stream.read_value<LEB128<size_t>>();
195 if (min_or_error.is_error())
196 return with_eof_check(stream, ParseError::ExpectedSize);
197 size_t min = min_or_error.release_value();
198
199 Optional<u32> max;
200 if (flag) {
201 auto value_or_error = stream.read_value<LEB128<size_t>>();
202 if (value_or_error.is_error())
203 return with_eof_check(stream, ParseError::ExpectedSize);
204 max = value_or_error.release_value();
205 }
206
207 return Limits { static_cast<u32>(min), move(max) };
208}
209
210ParseResult<MemoryType> MemoryType::parse(Stream& stream)
211{
212 ScopeLogger<WASM_BINPARSER_DEBUG> logger("MemoryType"sv);
213 auto limits_result = Limits::parse(stream);
214 if (limits_result.is_error())
215 return limits_result.error();
216 return MemoryType { limits_result.release_value() };
217}
218
219ParseResult<TableType> TableType::parse(Stream& stream)
220{
221 ScopeLogger<WASM_BINPARSER_DEBUG> logger("TableType"sv);
222 auto type_result = ValueType::parse(stream);
223 if (type_result.is_error())
224 return type_result.error();
225 if (!type_result.value().is_reference())
226 return with_eof_check(stream, ParseError::InvalidType);
227 auto limits_result = Limits::parse(stream);
228 if (limits_result.is_error())
229 return limits_result.error();
230 return TableType { type_result.release_value(), limits_result.release_value() };
231}
232
233ParseResult<GlobalType> GlobalType::parse(Stream& stream)
234{
235 ScopeLogger<WASM_BINPARSER_DEBUG> logger("GlobalType"sv);
236 auto type_result = ValueType::parse(stream);
237 if (type_result.is_error())
238 return type_result.error();
239
240 auto mutable_or_error = stream.read_value<u8>();
241 if (mutable_or_error.is_error())
242 return with_eof_check(stream, ParseError::ExpectedKindTag);
243
244 auto mutable_ = mutable_or_error.release_value();
245
246 if (mutable_ > 1)
247 return with_eof_check(stream, ParseError::InvalidTag);
248
249 return GlobalType { type_result.release_value(), mutable_ == 0x01 };
250}
251
252ParseResult<BlockType> BlockType::parse(Stream& stream)
253{
254 ScopeLogger<WASM_BINPARSER_DEBUG> logger("BlockType"sv);
255 auto kind_or_error = stream.read_value<u8>();
256 if (kind_or_error.is_error())
257 return with_eof_check(stream, ParseError::ExpectedKindTag);
258
259 auto kind = kind_or_error.release_value();
260 if (kind == Constants::empty_block_tag)
261 return BlockType {};
262
263 {
264 FixedMemoryStream value_stream { ReadonlyBytes { &kind, 1 } };
265 if (auto value_type = ValueType::parse(value_stream); !value_type.is_error())
266 return BlockType { value_type.release_value() };
267 }
268
269 ReconsumableStream new_stream { stream };
270 new_stream.unread({ &kind, 1 });
271
272 auto index_value_or_error = stream.read_value<LEB128<ssize_t>>();
273 if (index_value_or_error.is_error())
274 return with_eof_check(stream, ParseError::ExpectedIndex);
275 ssize_t index_value = index_value_or_error.release_value();
276
277 if (index_value < 0) {
278 dbgln("Invalid type index {}", index_value);
279 return with_eof_check(stream, ParseError::InvalidIndex);
280 }
281
282 return BlockType { TypeIndex(index_value) };
283}
284
285ParseResult<Vector<Instruction>> Instruction::parse(Stream& stream, InstructionPointer& ip)
286{
287 struct NestedInstructionState {
288 Vector<Instruction> prior_instructions;
289 OpCode opcode;
290 BlockType block_type;
291 InstructionPointer end_ip;
292 Optional<InstructionPointer> else_ip;
293 };
294 Vector<NestedInstructionState, 4> nested_instructions;
295 Vector<Instruction> resulting_instructions;
296
297 do {
298 ScopeLogger<WASM_BINPARSER_DEBUG> logger("Instruction"sv);
299 auto byte_or_error = stream.read_value<u8>();
300 if (byte_or_error.is_error())
301 return with_eof_check(stream, ParseError::ExpectedKindTag);
302
303 auto byte = byte_or_error.release_value();
304
305 if (!nested_instructions.is_empty()) {
306 auto& nested_structure = nested_instructions.last();
307 if (byte == 0x0b) {
308 // block/loop/if end
309 nested_structure.end_ip = ip + (nested_structure.else_ip.has_value() ? 1 : 0);
310 ++ip;
311
312 // Transform op(..., instr*) -> op(...) instr* op(end(ip))
313 auto instructions = move(nested_structure.prior_instructions);
314 instructions.ensure_capacity(instructions.size() + 2 + resulting_instructions.size());
315 instructions.append(Instruction { nested_structure.opcode, StructuredInstructionArgs { nested_structure.block_type, nested_structure.end_ip, nested_structure.else_ip } });
316 instructions.extend(move(resulting_instructions));
317 instructions.append(Instruction { Instructions::structured_end });
318 resulting_instructions = move(instructions);
319 nested_instructions.take_last();
320 continue;
321 }
322
323 if (byte == 0x05) {
324 // if...else
325
326 // Transform op(..., instr*, instr*) -> op(...) instr* op(else(ip) instr* op(end(ip))
327 resulting_instructions.append(Instruction { Instructions::structured_else });
328 ++ip;
329 nested_structure.else_ip = ip.value();
330 continue;
331 }
332 }
333
334 OpCode opcode { byte };
335 ++ip;
336
337 switch (opcode.value()) {
338 case Instructions::block.value():
339 case Instructions::loop.value():
340 case Instructions::if_.value(): {
341 auto block_type = BlockType::parse(stream);
342 if (block_type.is_error())
343 return block_type.error();
344
345 nested_instructions.append({ move(resulting_instructions), opcode, block_type.release_value(), {}, {} });
346 resulting_instructions = {};
347 break;
348 }
349 case Instructions::br.value():
350 case Instructions::br_if.value(): {
351 // branches with a single label immediate
352 auto index = GenericIndexParser<LabelIndex>::parse(stream);
353 if (index.is_error())
354 return index.error();
355
356 resulting_instructions.append(Instruction { opcode, index.release_value() });
357 break;
358 }
359 case Instructions::br_table.value(): {
360 // br_table label* label
361 auto labels = parse_vector<GenericIndexParser<LabelIndex>>(stream);
362 if (labels.is_error())
363 return labels.error();
364
365 auto default_label = GenericIndexParser<LabelIndex>::parse(stream);
366 if (default_label.is_error())
367 return default_label.error();
368
369 resulting_instructions.append(Instruction { opcode, TableBranchArgs { labels.release_value(), default_label.release_value() } });
370 break;
371 }
372 case Instructions::call.value(): {
373 // call function
374 auto function_index = GenericIndexParser<FunctionIndex>::parse(stream);
375 if (function_index.is_error())
376 return function_index.error();
377
378 resulting_instructions.append(Instruction { opcode, function_index.release_value() });
379 break;
380 }
381 case Instructions::call_indirect.value(): {
382 // call_indirect type table
383 auto type_index = GenericIndexParser<TypeIndex>::parse(stream);
384 if (type_index.is_error())
385 return type_index.error();
386
387 auto table_index = GenericIndexParser<TableIndex>::parse(stream);
388 if (table_index.is_error())
389 return table_index.error();
390
391 resulting_instructions.append(Instruction { opcode, IndirectCallArgs { type_index.release_value(), table_index.release_value() } });
392 break;
393 }
394 case Instructions::i32_load.value():
395 case Instructions::i64_load.value():
396 case Instructions::f32_load.value():
397 case Instructions::f64_load.value():
398 case Instructions::i32_load8_s.value():
399 case Instructions::i32_load8_u.value():
400 case Instructions::i32_load16_s.value():
401 case Instructions::i32_load16_u.value():
402 case Instructions::i64_load8_s.value():
403 case Instructions::i64_load8_u.value():
404 case Instructions::i64_load16_s.value():
405 case Instructions::i64_load16_u.value():
406 case Instructions::i64_load32_s.value():
407 case Instructions::i64_load32_u.value():
408 case Instructions::i32_store.value():
409 case Instructions::i64_store.value():
410 case Instructions::f32_store.value():
411 case Instructions::f64_store.value():
412 case Instructions::i32_store8.value():
413 case Instructions::i32_store16.value():
414 case Instructions::i64_store8.value():
415 case Instructions::i64_store16.value():
416 case Instructions::i64_store32.value(): {
417 // op (align offset)
418 auto align_or_error = stream.read_value<LEB128<size_t>>();
419 if (align_or_error.is_error())
420 return with_eof_check(stream, ParseError::InvalidInput);
421 size_t align = align_or_error.release_value();
422
423 auto offset_or_error = stream.read_value<LEB128<size_t>>();
424 if (offset_or_error.is_error())
425 return with_eof_check(stream, ParseError::InvalidInput);
426 size_t offset = offset_or_error.release_value();
427
428 resulting_instructions.append(Instruction { opcode, MemoryArgument { static_cast<u32>(align), static_cast<u32>(offset) } });
429 break;
430 }
431 case Instructions::local_get.value():
432 case Instructions::local_set.value():
433 case Instructions::local_tee.value(): {
434 auto index = GenericIndexParser<LocalIndex>::parse(stream);
435 if (index.is_error())
436 return index.error();
437
438 resulting_instructions.append(Instruction { opcode, index.release_value() });
439 break;
440 }
441 case Instructions::global_get.value():
442 case Instructions::global_set.value(): {
443 auto index = GenericIndexParser<GlobalIndex>::parse(stream);
444 if (index.is_error())
445 return index.error();
446
447 resulting_instructions.append(Instruction { opcode, index.release_value() });
448 break;
449 }
450 case Instructions::memory_size.value():
451 case Instructions::memory_grow.value(): {
452 // op 0x0
453 // The zero is currently unused.
454 auto unused_or_error = stream.read_value<u8>();
455 if (unused_or_error.is_error())
456 return with_eof_check(stream, ParseError::ExpectedKindTag);
457
458 auto unused = unused_or_error.release_value();
459 if (unused != 0x00) {
460 dbgln("Invalid tag in memory_grow {}", unused);
461 return with_eof_check(stream, ParseError::InvalidTag);
462 }
463
464 resulting_instructions.append(Instruction { opcode });
465 break;
466 }
467 case Instructions::i32_const.value(): {
468 auto value_or_error = stream.read_value<LEB128<i32>>();
469 if (value_or_error.is_error())
470 return with_eof_check(stream, ParseError::ExpectedSignedImmediate);
471 i32 value = value_or_error.release_value();
472
473 resulting_instructions.append(Instruction { opcode, value });
474 break;
475 }
476 case Instructions::i64_const.value(): {
477 // op literal
478 auto value_or_error = stream.read_value<LEB128<i64>>();
479 if (value_or_error.is_error())
480 return with_eof_check(stream, ParseError::ExpectedSignedImmediate);
481 i64 value = value_or_error.release_value();
482
483 resulting_instructions.append(Instruction { opcode, value });
484 break;
485 }
486 case Instructions::f32_const.value(): {
487 // op literal
488 LittleEndian<u32> value;
489 if (stream.read_until_filled(value.bytes()).is_error())
490 return with_eof_check(stream, ParseError::ExpectedFloatingImmediate);
491
492 auto floating = bit_cast<float>(static_cast<u32>(value));
493 resulting_instructions.append(Instruction { opcode, floating });
494 break;
495 }
496 case Instructions::f64_const.value(): {
497 // op literal
498 LittleEndian<u64> value;
499 if (stream.read_until_filled(value.bytes()).is_error())
500 return with_eof_check(stream, ParseError::ExpectedFloatingImmediate);
501
502 auto floating = bit_cast<double>(static_cast<u64>(value));
503 resulting_instructions.append(Instruction { opcode, floating });
504 break;
505 }
506 case Instructions::table_get.value():
507 case Instructions::table_set.value(): {
508 auto index = GenericIndexParser<TableIndex>::parse(stream);
509 if (index.is_error())
510 return index.error();
511
512 resulting_instructions.append(Instruction { opcode, index.release_value() });
513 break;
514 }
515 case Instructions::select_typed.value(): {
516 auto types = parse_vector<ValueType>(stream);
517 if (types.is_error())
518 return types.error();
519
520 resulting_instructions.append(Instruction { opcode, types.release_value() });
521 break;
522 }
523 case Instructions::ref_null.value(): {
524 auto type = ValueType::parse(stream);
525 if (type.is_error())
526 return type.error();
527 if (!type.value().is_reference())
528 return ParseError::InvalidType;
529
530 resulting_instructions.append(Instruction { opcode, type.release_value() });
531 break;
532 }
533 case Instructions::ref_func.value(): {
534 auto index = GenericIndexParser<FunctionIndex>::parse(stream);
535 if (index.is_error())
536 return index.error();
537
538 resulting_instructions.append(Instruction { opcode, index.release_value() });
539 break;
540 }
541 case Instructions::ref_is_null.value():
542 case Instructions::unreachable.value():
543 case Instructions::nop.value():
544 case Instructions::return_.value():
545 case Instructions::drop.value():
546 case Instructions::select.value():
547 case Instructions::i32_eqz.value():
548 case Instructions::i32_eq.value():
549 case Instructions::i32_ne.value():
550 case Instructions::i32_lts.value():
551 case Instructions::i32_ltu.value():
552 case Instructions::i32_gts.value():
553 case Instructions::i32_gtu.value():
554 case Instructions::i32_les.value():
555 case Instructions::i32_leu.value():
556 case Instructions::i32_ges.value():
557 case Instructions::i32_geu.value():
558 case Instructions::i64_eqz.value():
559 case Instructions::i64_eq.value():
560 case Instructions::i64_ne.value():
561 case Instructions::i64_lts.value():
562 case Instructions::i64_ltu.value():
563 case Instructions::i64_gts.value():
564 case Instructions::i64_gtu.value():
565 case Instructions::i64_les.value():
566 case Instructions::i64_leu.value():
567 case Instructions::i64_ges.value():
568 case Instructions::i64_geu.value():
569 case Instructions::f32_eq.value():
570 case Instructions::f32_ne.value():
571 case Instructions::f32_lt.value():
572 case Instructions::f32_gt.value():
573 case Instructions::f32_le.value():
574 case Instructions::f32_ge.value():
575 case Instructions::f64_eq.value():
576 case Instructions::f64_ne.value():
577 case Instructions::f64_lt.value():
578 case Instructions::f64_gt.value():
579 case Instructions::f64_le.value():
580 case Instructions::f64_ge.value():
581 case Instructions::i32_clz.value():
582 case Instructions::i32_ctz.value():
583 case Instructions::i32_popcnt.value():
584 case Instructions::i32_add.value():
585 case Instructions::i32_sub.value():
586 case Instructions::i32_mul.value():
587 case Instructions::i32_divs.value():
588 case Instructions::i32_divu.value():
589 case Instructions::i32_rems.value():
590 case Instructions::i32_remu.value():
591 case Instructions::i32_and.value():
592 case Instructions::i32_or.value():
593 case Instructions::i32_xor.value():
594 case Instructions::i32_shl.value():
595 case Instructions::i32_shrs.value():
596 case Instructions::i32_shru.value():
597 case Instructions::i32_rotl.value():
598 case Instructions::i32_rotr.value():
599 case Instructions::i64_clz.value():
600 case Instructions::i64_ctz.value():
601 case Instructions::i64_popcnt.value():
602 case Instructions::i64_add.value():
603 case Instructions::i64_sub.value():
604 case Instructions::i64_mul.value():
605 case Instructions::i64_divs.value():
606 case Instructions::i64_divu.value():
607 case Instructions::i64_rems.value():
608 case Instructions::i64_remu.value():
609 case Instructions::i64_and.value():
610 case Instructions::i64_or.value():
611 case Instructions::i64_xor.value():
612 case Instructions::i64_shl.value():
613 case Instructions::i64_shrs.value():
614 case Instructions::i64_shru.value():
615 case Instructions::i64_rotl.value():
616 case Instructions::i64_rotr.value():
617 case Instructions::f32_abs.value():
618 case Instructions::f32_neg.value():
619 case Instructions::f32_ceil.value():
620 case Instructions::f32_floor.value():
621 case Instructions::f32_trunc.value():
622 case Instructions::f32_nearest.value():
623 case Instructions::f32_sqrt.value():
624 case Instructions::f32_add.value():
625 case Instructions::f32_sub.value():
626 case Instructions::f32_mul.value():
627 case Instructions::f32_div.value():
628 case Instructions::f32_min.value():
629 case Instructions::f32_max.value():
630 case Instructions::f32_copysign.value():
631 case Instructions::f64_abs.value():
632 case Instructions::f64_neg.value():
633 case Instructions::f64_ceil.value():
634 case Instructions::f64_floor.value():
635 case Instructions::f64_trunc.value():
636 case Instructions::f64_nearest.value():
637 case Instructions::f64_sqrt.value():
638 case Instructions::f64_add.value():
639 case Instructions::f64_sub.value():
640 case Instructions::f64_mul.value():
641 case Instructions::f64_div.value():
642 case Instructions::f64_min.value():
643 case Instructions::f64_max.value():
644 case Instructions::f64_copysign.value():
645 case Instructions::i32_wrap_i64.value():
646 case Instructions::i32_trunc_sf32.value():
647 case Instructions::i32_trunc_uf32.value():
648 case Instructions::i32_trunc_sf64.value():
649 case Instructions::i32_trunc_uf64.value():
650 case Instructions::i64_extend_si32.value():
651 case Instructions::i64_extend_ui32.value():
652 case Instructions::i64_trunc_sf32.value():
653 case Instructions::i64_trunc_uf32.value():
654 case Instructions::i64_trunc_sf64.value():
655 case Instructions::i64_trunc_uf64.value():
656 case Instructions::f32_convert_si32.value():
657 case Instructions::f32_convert_ui32.value():
658 case Instructions::f32_convert_si64.value():
659 case Instructions::f32_convert_ui64.value():
660 case Instructions::f32_demote_f64.value():
661 case Instructions::f64_convert_si32.value():
662 case Instructions::f64_convert_ui32.value():
663 case Instructions::f64_convert_si64.value():
664 case Instructions::f64_convert_ui64.value():
665 case Instructions::f64_promote_f32.value():
666 case Instructions::i32_reinterpret_f32.value():
667 case Instructions::i64_reinterpret_f64.value():
668 case Instructions::f32_reinterpret_i32.value():
669 case Instructions::f64_reinterpret_i64.value():
670 case Instructions::i32_extend8_s.value():
671 case Instructions::i32_extend16_s.value():
672 case Instructions::i64_extend8_s.value():
673 case Instructions::i64_extend16_s.value():
674 case Instructions::i64_extend32_s.value():
675 resulting_instructions.append(Instruction { opcode });
676 break;
677 case 0xfc: {
678 // These are multibyte instructions.
679 auto selector_or_error = stream.read_value<LEB128<u32>>();
680 if (selector_or_error.is_error())
681 return with_eof_check(stream, ParseError::InvalidInput);
682 u32 selector = selector_or_error.release_value();
683 switch (selector) {
684 case Instructions::i32_trunc_sat_f32_s_second:
685 case Instructions::i32_trunc_sat_f32_u_second:
686 case Instructions::i32_trunc_sat_f64_s_second:
687 case Instructions::i32_trunc_sat_f64_u_second:
688 case Instructions::i64_trunc_sat_f32_s_second:
689 case Instructions::i64_trunc_sat_f32_u_second:
690 case Instructions::i64_trunc_sat_f64_s_second:
691 case Instructions::i64_trunc_sat_f64_u_second:
692 resulting_instructions.append(Instruction { OpCode { 0xfc00 | selector } });
693 break;
694 case Instructions::memory_init_second: {
695 auto index = GenericIndexParser<DataIndex>::parse(stream);
696 if (index.is_error())
697 return index.error();
698 auto unused_or_error = stream.read_value<u8>();
699 if (unused_or_error.is_error())
700 return with_eof_check(stream, ParseError::InvalidInput);
701
702 auto unused = unused_or_error.release_value();
703 if (unused != 0x00)
704 return ParseError::InvalidImmediate;
705 resulting_instructions.append(Instruction { OpCode { 0xfc00 | selector }, index.release_value() });
706 break;
707 }
708 case Instructions::data_drop_second: {
709 auto index = GenericIndexParser<DataIndex>::parse(stream);
710 if (index.is_error())
711 return index.error();
712 resulting_instructions.append(Instruction { OpCode { 0xfc00 | selector }, index.release_value() });
713 break;
714 }
715 case Instructions::memory_copy_second: {
716 for (size_t i = 0; i < 2; ++i) {
717 auto unused_or_error = stream.read_value<u8>();
718 if (unused_or_error.is_error())
719 return with_eof_check(stream, ParseError::InvalidInput);
720
721 auto unused = unused_or_error.release_value();
722 if (unused != 0x00)
723 return ParseError::InvalidImmediate;
724 }
725 resulting_instructions.append(Instruction { OpCode { 0xfc00 | selector } });
726 break;
727 }
728 case Instructions::memory_fill_second: {
729 auto unused_or_error = stream.read_value<u8>();
730 if (unused_or_error.is_error())
731 return with_eof_check(stream, ParseError::InvalidInput);
732
733 auto unused = unused_or_error.release_value();
734 if (unused != 0x00)
735 return ParseError::InvalidImmediate;
736 resulting_instructions.append(Instruction { OpCode { 0xfc00 | selector } });
737 break;
738 }
739 case Instructions::table_init_second: {
740 auto element_index = GenericIndexParser<ElementIndex>::parse(stream);
741 if (element_index.is_error())
742 return element_index.error();
743 auto table_index = GenericIndexParser<TableIndex>::parse(stream);
744 if (table_index.is_error())
745 return table_index.error();
746 resulting_instructions.append(Instruction { OpCode { 0xfc00 | selector }, TableElementArgs { element_index.release_value(), table_index.release_value() } });
747 break;
748 }
749 case Instructions::elem_drop_second: {
750 auto element_index = GenericIndexParser<ElementIndex>::parse(stream);
751 if (element_index.is_error())
752 return element_index.error();
753 resulting_instructions.append(Instruction { OpCode { 0xfc00 | selector }, element_index.release_value() });
754 break;
755 }
756 case Instructions::table_copy_second: {
757 auto lhs = GenericIndexParser<TableIndex>::parse(stream);
758 if (lhs.is_error())
759 return lhs.error();
760 auto rhs = GenericIndexParser<TableIndex>::parse(stream);
761 if (rhs.is_error())
762 return rhs.error();
763 resulting_instructions.append(Instruction { OpCode { 0xfc00 | selector }, TableTableArgs { lhs.release_value(), rhs.release_value() } });
764 break;
765 }
766 case Instructions::table_grow_second:
767 case Instructions::table_size_second:
768 case Instructions::table_fill_second: {
769 auto index = GenericIndexParser<TableIndex>::parse(stream);
770 if (index.is_error())
771 return index.error();
772 resulting_instructions.append(Instruction { OpCode { 0xfc00 | selector }, index.release_value() });
773 break;
774 }
775 default:
776 return ParseError::UnknownInstruction;
777 }
778 }
779 }
780 } while (!nested_instructions.is_empty());
781
782 return resulting_instructions;
783}
784
785ParseResult<CustomSection> CustomSection::parse(Stream& stream)
786{
787 ScopeLogger<WASM_BINPARSER_DEBUG> logger("CustomSection"sv);
788 auto name = parse_name(stream);
789 if (name.is_error())
790 return name.error();
791
792 ByteBuffer data_buffer;
793 if (data_buffer.try_resize(64).is_error())
794 return ParseError::OutOfMemory;
795
796 while (!stream.is_eof()) {
797 char buf[16];
798 auto span_or_error = stream.read_some({ buf, 16 });
799 if (span_or_error.is_error())
800 break;
801 auto size = span_or_error.release_value().size();
802 if (size == 0)
803 break;
804 if (data_buffer.try_append(buf, size).is_error())
805 return with_eof_check(stream, ParseError::HugeAllocationRequested);
806 }
807
808 return CustomSection(name.release_value(), move(data_buffer));
809}
810
811ParseResult<TypeSection> TypeSection::parse(Stream& stream)
812{
813 ScopeLogger<WASM_BINPARSER_DEBUG> logger("TypeSection"sv);
814 auto types = parse_vector<FunctionType>(stream);
815 if (types.is_error())
816 return types.error();
817 return TypeSection { types.release_value() };
818}
819
820ParseResult<ImportSection::Import> ImportSection::Import::parse(Stream& stream)
821{
822 ScopeLogger<WASM_BINPARSER_DEBUG> logger("Import"sv);
823 auto module = parse_name(stream);
824 if (module.is_error())
825 return module.error();
826 auto name = parse_name(stream);
827 if (name.is_error())
828 return name.error();
829 auto tag_or_error = stream.read_value<u8>();
830 if (tag_or_error.is_error())
831 return with_eof_check(stream, ParseError::ExpectedKindTag);
832
833 auto tag = tag_or_error.release_value();
834
835 switch (tag) {
836 case Constants::extern_function_tag: {
837 auto index = GenericIndexParser<TypeIndex>::parse(stream);
838 if (index.is_error())
839 return index.error();
840 return Import { module.release_value(), name.release_value(), index.release_value() };
841 }
842 case Constants::extern_table_tag:
843 return parse_with_type<TableType>(stream, module, name);
844 case Constants::extern_memory_tag:
845 return parse_with_type<MemoryType>(stream, module, name);
846 case Constants::extern_global_tag:
847 return parse_with_type<GlobalType>(stream, module, name);
848 default:
849 return with_eof_check(stream, ParseError::InvalidTag);
850 }
851}
852
853ParseResult<ImportSection> ImportSection::parse(Stream& stream)
854{
855 ScopeLogger<WASM_BINPARSER_DEBUG> logger("ImportSection"sv);
856 auto imports = parse_vector<Import>(stream);
857 if (imports.is_error())
858 return imports.error();
859 return ImportSection { imports.release_value() };
860}
861
862ParseResult<FunctionSection> FunctionSection::parse(Stream& stream)
863{
864 ScopeLogger<WASM_BINPARSER_DEBUG> logger("FunctionSection"sv);
865 auto indices = parse_vector<size_t>(stream);
866 if (indices.is_error())
867 return indices.error();
868
869 Vector<TypeIndex> typed_indices;
870 typed_indices.ensure_capacity(indices.value().size());
871 for (auto entry : indices.value())
872 typed_indices.append(entry);
873
874 return FunctionSection { move(typed_indices) };
875}
876
877ParseResult<TableSection::Table> TableSection::Table::parse(Stream& stream)
878{
879 ScopeLogger<WASM_BINPARSER_DEBUG> logger("Table"sv);
880 auto type = TableType::parse(stream);
881 if (type.is_error())
882 return type.error();
883 return Table { type.release_value() };
884}
885
886ParseResult<TableSection> TableSection::parse(Stream& stream)
887{
888 ScopeLogger<WASM_BINPARSER_DEBUG> logger("TableSection"sv);
889 auto tables = parse_vector<Table>(stream);
890 if (tables.is_error())
891 return tables.error();
892 return TableSection { tables.release_value() };
893}
894
895ParseResult<MemorySection::Memory> MemorySection::Memory::parse(Stream& stream)
896{
897 ScopeLogger<WASM_BINPARSER_DEBUG> logger("Memory"sv);
898 auto type = MemoryType::parse(stream);
899 if (type.is_error())
900 return type.error();
901 return Memory { type.release_value() };
902}
903
904ParseResult<MemorySection> MemorySection::parse(Stream& stream)
905{
906 ScopeLogger<WASM_BINPARSER_DEBUG> logger("MemorySection"sv);
907 auto memories = parse_vector<Memory>(stream);
908 if (memories.is_error())
909 return memories.error();
910 return MemorySection { memories.release_value() };
911}
912
913ParseResult<Expression> Expression::parse(Stream& stream)
914{
915 ScopeLogger<WASM_BINPARSER_DEBUG> logger("Expression"sv);
916 InstructionPointer ip { 0 };
917 auto instructions = parse_until_any_of<Instruction, 0x0b>(stream, ip);
918 if (instructions.is_error())
919 return instructions.error();
920
921 return Expression { move(instructions.value().values) };
922}
923
924ParseResult<GlobalSection::Global> GlobalSection::Global::parse(Stream& stream)
925{
926 ScopeLogger<WASM_BINPARSER_DEBUG> logger("Global"sv);
927 auto type = GlobalType::parse(stream);
928 if (type.is_error())
929 return type.error();
930 auto exprs = Expression::parse(stream);
931 if (exprs.is_error())
932 return exprs.error();
933 return Global { type.release_value(), exprs.release_value() };
934}
935
936ParseResult<GlobalSection> GlobalSection::parse(Stream& stream)
937{
938 ScopeLogger<WASM_BINPARSER_DEBUG> logger("GlobalSection"sv);
939 auto result = parse_vector<Global>(stream);
940 if (result.is_error())
941 return result.error();
942 return GlobalSection { result.release_value() };
943}
944
945ParseResult<ExportSection::Export> ExportSection::Export::parse(Stream& stream)
946{
947 ScopeLogger<WASM_BINPARSER_DEBUG> logger("Export"sv);
948 auto name = parse_name(stream);
949 if (name.is_error())
950 return name.error();
951 auto tag_or_error = stream.read_value<u8>();
952 if (tag_or_error.is_error())
953 return with_eof_check(stream, ParseError::ExpectedKindTag);
954
955 auto tag = tag_or_error.release_value();
956
957 auto index_or_error = stream.read_value<LEB128<size_t>>();
958 if (index_or_error.is_error())
959 return with_eof_check(stream, ParseError::ExpectedIndex);
960 size_t index = index_or_error.release_value();
961
962 switch (tag) {
963 case Constants::extern_function_tag:
964 return Export { name.release_value(), ExportDesc { FunctionIndex { index } } };
965 case Constants::extern_table_tag:
966 return Export { name.release_value(), ExportDesc { TableIndex { index } } };
967 case Constants::extern_memory_tag:
968 return Export { name.release_value(), ExportDesc { MemoryIndex { index } } };
969 case Constants::extern_global_tag:
970 return Export { name.release_value(), ExportDesc { GlobalIndex { index } } };
971 default:
972 return with_eof_check(stream, ParseError::InvalidTag);
973 }
974}
975
976ParseResult<ExportSection> ExportSection::parse(Stream& stream)
977{
978 ScopeLogger<WASM_BINPARSER_DEBUG> logger("ExportSection"sv);
979 auto result = parse_vector<Export>(stream);
980 if (result.is_error())
981 return result.error();
982 return ExportSection { result.release_value() };
983}
984
985ParseResult<StartSection::StartFunction> StartSection::StartFunction::parse(Stream& stream)
986{
987 ScopeLogger<WASM_BINPARSER_DEBUG> logger("StartFunction"sv);
988 auto index = GenericIndexParser<FunctionIndex>::parse(stream);
989 if (index.is_error())
990 return index.error();
991 return StartFunction { index.release_value() };
992}
993
994ParseResult<StartSection> StartSection::parse(Stream& stream)
995{
996 ScopeLogger<WASM_BINPARSER_DEBUG> logger("StartSection"sv);
997 auto result = StartFunction::parse(stream);
998 if (result.is_error())
999 return result.error();
1000 return StartSection { result.release_value() };
1001}
1002
1003ParseResult<ElementSection::SegmentType0> ElementSection::SegmentType0::parse(Stream& stream)
1004{
1005 auto expression = Expression::parse(stream);
1006 if (expression.is_error())
1007 return expression.error();
1008 auto indices = parse_vector<GenericIndexParser<FunctionIndex>>(stream);
1009 if (indices.is_error())
1010 return indices.error();
1011
1012 return SegmentType0 { indices.release_value(), Active { 0, expression.release_value() } };
1013}
1014
1015ParseResult<ElementSection::SegmentType1> ElementSection::SegmentType1::parse(Stream& stream)
1016{
1017 auto kind_or_error = stream.read_value<u8>();
1018 if (kind_or_error.is_error())
1019 return with_eof_check(stream, ParseError::ExpectedKindTag);
1020
1021 auto kind = kind_or_error.release_value();
1022 if (kind != 0)
1023 return ParseError::InvalidTag;
1024 auto indices = parse_vector<GenericIndexParser<FunctionIndex>>(stream);
1025 if (indices.is_error())
1026 return indices.error();
1027
1028 return SegmentType1 { indices.release_value() };
1029}
1030
1031ParseResult<ElementSection::SegmentType2> ElementSection::SegmentType2::parse(Stream& stream)
1032{
1033 dbgln("Type 2");
1034 (void)stream;
1035 return ParseError::NotImplemented;
1036}
1037
1038ParseResult<ElementSection::SegmentType3> ElementSection::SegmentType3::parse(Stream& stream)
1039{
1040 dbgln("Type 3");
1041 (void)stream;
1042 return ParseError::NotImplemented;
1043}
1044
1045ParseResult<ElementSection::SegmentType4> ElementSection::SegmentType4::parse(Stream& stream)
1046{
1047 dbgln("Type 4");
1048 (void)stream;
1049 return ParseError::NotImplemented;
1050}
1051
1052ParseResult<ElementSection::SegmentType5> ElementSection::SegmentType5::parse(Stream& stream)
1053{
1054 dbgln("Type 5");
1055 (void)stream;
1056 return ParseError::NotImplemented;
1057}
1058
1059ParseResult<ElementSection::SegmentType6> ElementSection::SegmentType6::parse(Stream& stream)
1060{
1061 dbgln("Type 6");
1062 (void)stream;
1063 return ParseError::NotImplemented;
1064}
1065
1066ParseResult<ElementSection::SegmentType7> ElementSection::SegmentType7::parse(Stream& stream)
1067{
1068 dbgln("Type 7");
1069 (void)stream;
1070 return ParseError::NotImplemented;
1071}
1072
1073ParseResult<ElementSection::Element> ElementSection::Element::parse(Stream& stream)
1074{
1075 ScopeLogger<WASM_BINPARSER_DEBUG> logger("Element"sv);
1076 auto tag_or_error = stream.read_value<u8>();
1077 if (tag_or_error.is_error())
1078 return with_eof_check(stream, ParseError::ExpectedKindTag);
1079
1080 auto tag = tag_or_error.release_value();
1081
1082 switch (tag) {
1083 case 0x00:
1084 if (auto result = SegmentType0::parse(stream); result.is_error()) {
1085 return result.error();
1086 } else {
1087 Vector<Instruction> instructions;
1088 for (auto& index : result.value().function_indices)
1089 instructions.empend(Instructions::ref_func, index);
1090 return Element { ValueType(ValueType::FunctionReference), { Expression { move(instructions) } }, move(result.value().mode) };
1091 }
1092 case 0x01:
1093 if (auto result = SegmentType1::parse(stream); result.is_error()) {
1094 return result.error();
1095 } else {
1096 Vector<Instruction> instructions;
1097 for (auto& index : result.value().function_indices)
1098 instructions.empend(Instructions::ref_func, index);
1099 return Element { ValueType(ValueType::FunctionReference), { Expression { move(instructions) } }, Passive {} };
1100 }
1101 case 0x02:
1102 if (auto result = SegmentType2::parse(stream); result.is_error()) {
1103 return result.error();
1104 } else {
1105 return ParseError::NotImplemented;
1106 }
1107 case 0x03:
1108 if (auto result = SegmentType3::parse(stream); result.is_error()) {
1109 return result.error();
1110 } else {
1111 return ParseError::NotImplemented;
1112 }
1113 case 0x04:
1114 if (auto result = SegmentType4::parse(stream); result.is_error()) {
1115 return result.error();
1116 } else {
1117 return ParseError::NotImplemented;
1118 }
1119 case 0x05:
1120 if (auto result = SegmentType5::parse(stream); result.is_error()) {
1121 return result.error();
1122 } else {
1123 return ParseError::NotImplemented;
1124 }
1125 case 0x06:
1126 if (auto result = SegmentType6::parse(stream); result.is_error()) {
1127 return result.error();
1128 } else {
1129 return ParseError::NotImplemented;
1130 }
1131 case 0x07:
1132 if (auto result = SegmentType7::parse(stream); result.is_error()) {
1133 return result.error();
1134 } else {
1135 return ParseError::NotImplemented;
1136 }
1137 default:
1138 return ParseError::InvalidTag;
1139 }
1140}
1141
1142ParseResult<ElementSection> ElementSection::parse(Stream& stream)
1143{
1144 ScopeLogger<WASM_BINPARSER_DEBUG> logger("ElementSection"sv);
1145 auto result = parse_vector<Element>(stream);
1146 if (result.is_error())
1147 return result.error();
1148 return ElementSection { result.release_value() };
1149}
1150
1151ParseResult<Locals> Locals::parse(Stream& stream)
1152{
1153 ScopeLogger<WASM_BINPARSER_DEBUG> logger("Locals"sv);
1154 auto count_or_error = stream.read_value<LEB128<size_t>>();
1155 if (count_or_error.is_error())
1156 return with_eof_check(stream, ParseError::InvalidSize);
1157 size_t count = count_or_error.release_value();
1158
1159 if (count > Constants::max_allowed_function_locals_per_type)
1160 return with_eof_check(stream, ParseError::HugeAllocationRequested);
1161
1162 auto type = ValueType::parse(stream);
1163 if (type.is_error())
1164 return type.error();
1165
1166 return Locals { static_cast<u32>(count), type.release_value() };
1167}
1168
1169ParseResult<CodeSection::Func> CodeSection::Func::parse(Stream& stream)
1170{
1171 ScopeLogger<WASM_BINPARSER_DEBUG> logger("Func"sv);
1172 auto locals = parse_vector<Locals>(stream);
1173 if (locals.is_error())
1174 return locals.error();
1175 auto body = Expression::parse(stream);
1176 if (body.is_error())
1177 return body.error();
1178 return Func { locals.release_value(), body.release_value() };
1179}
1180
1181ParseResult<CodeSection::Code> CodeSection::Code::parse(Stream& stream)
1182{
1183 ScopeLogger<WASM_BINPARSER_DEBUG> logger("Code"sv);
1184 auto size_or_error = stream.read_value<LEB128<size_t>>();
1185 if (size_or_error.is_error())
1186 return with_eof_check(stream, ParseError::InvalidSize);
1187 size_t size = size_or_error.release_value();
1188
1189 auto constrained_stream = ConstrainedStream { stream, size };
1190
1191 auto func = Func::parse(constrained_stream);
1192 if (func.is_error())
1193 return func.error();
1194
1195 return Code { static_cast<u32>(size), func.release_value() };
1196}
1197
1198ParseResult<CodeSection> CodeSection::parse(Stream& stream)
1199{
1200 ScopeLogger<WASM_BINPARSER_DEBUG> logger("CodeSection"sv);
1201 auto result = parse_vector<Code>(stream);
1202 if (result.is_error())
1203 return result.error();
1204 return CodeSection { result.release_value() };
1205}
1206
1207ParseResult<DataSection::Data> DataSection::Data::parse(Stream& stream)
1208{
1209 ScopeLogger<WASM_BINPARSER_DEBUG> logger("Data"sv);
1210 auto tag_or_error = stream.read_value<u8>();
1211 if (tag_or_error.is_error())
1212 return with_eof_check(stream, ParseError::ExpectedKindTag);
1213
1214 auto tag = tag_or_error.release_value();
1215
1216 if (tag > 0x02)
1217 return with_eof_check(stream, ParseError::InvalidTag);
1218
1219 if (tag == 0x00) {
1220 auto expr = Expression::parse(stream);
1221 if (expr.is_error())
1222 return expr.error();
1223 auto init = parse_vector<u8>(stream);
1224 if (init.is_error())
1225 return init.error();
1226 return Data { Active { init.release_value(), { 0 }, expr.release_value() } };
1227 }
1228 if (tag == 0x01) {
1229 auto init = parse_vector<u8>(stream);
1230 if (init.is_error())
1231 return init.error();
1232 return Data { Passive { init.release_value() } };
1233 }
1234 if (tag == 0x02) {
1235 auto index = GenericIndexParser<MemoryIndex>::parse(stream);
1236 if (index.is_error())
1237 return index.error();
1238 auto expr = Expression::parse(stream);
1239 if (expr.is_error())
1240 return expr.error();
1241 auto init = parse_vector<u8>(stream);
1242 if (init.is_error())
1243 return init.error();
1244 return Data { Active { init.release_value(), index.release_value(), expr.release_value() } };
1245 }
1246 VERIFY_NOT_REACHED();
1247}
1248
1249ParseResult<DataSection> DataSection::parse(Stream& stream)
1250{
1251 ScopeLogger<WASM_BINPARSER_DEBUG> logger("DataSection"sv);
1252 auto data = parse_vector<Data>(stream);
1253 if (data.is_error())
1254 return data.error();
1255
1256 return DataSection { data.release_value() };
1257}
1258
1259ParseResult<DataCountSection> DataCountSection::parse([[maybe_unused]] Stream& stream)
1260{
1261 ScopeLogger<WASM_BINPARSER_DEBUG> logger("DataCountSection"sv);
1262 auto value_or_error = stream.read_value<LEB128<u32>>();
1263 if (value_or_error.is_error()) {
1264 if (stream.is_eof()) {
1265 // The section simply didn't contain anything.
1266 return DataCountSection { {} };
1267 }
1268 return ParseError::ExpectedSize;
1269 }
1270 u32 value = value_or_error.release_value();
1271
1272 return DataCountSection { value };
1273}
1274
1275ParseResult<Module> Module::parse(Stream& stream)
1276{
1277 ScopeLogger<WASM_BINPARSER_DEBUG> logger("Module"sv);
1278 u8 buf[4];
1279 if (stream.read_until_filled({ buf, 4 }).is_error())
1280 return with_eof_check(stream, ParseError::InvalidInput);
1281 if (Bytes { buf, 4 } != wasm_magic.span())
1282 return with_eof_check(stream, ParseError::InvalidModuleMagic);
1283
1284 if (stream.read_until_filled({ buf, 4 }).is_error())
1285 return with_eof_check(stream, ParseError::InvalidInput);
1286 if (Bytes { buf, 4 } != wasm_version.span())
1287 return with_eof_check(stream, ParseError::InvalidModuleVersion);
1288
1289 Vector<AnySection> sections;
1290 for (;;) {
1291 auto section_id_or_error = stream.read_value<u8>();
1292 if (stream.is_eof())
1293 break;
1294 if (section_id_or_error.is_error())
1295 return with_eof_check(stream, ParseError::ExpectedIndex);
1296
1297 auto section_id = section_id_or_error.release_value();
1298
1299 auto section_size_or_error = stream.read_value<LEB128<size_t>>();
1300 if (section_size_or_error.is_error())
1301 return with_eof_check(stream, ParseError::ExpectedSize);
1302 size_t section_size = section_size_or_error.release_value();
1303
1304 auto section_stream = ConstrainedStream { stream, section_size };
1305
1306 switch (section_id) {
1307 case CustomSection::section_id:
1308 sections.append(TRY(CustomSection::parse(section_stream)));
1309 continue;
1310 case TypeSection::section_id:
1311 sections.append(TRY(TypeSection::parse(section_stream)));
1312 continue;
1313 case ImportSection::section_id:
1314 sections.append(TRY(ImportSection::parse(section_stream)));
1315 continue;
1316 case FunctionSection::section_id:
1317 sections.append(TRY(FunctionSection::parse(section_stream)));
1318 continue;
1319 case TableSection::section_id:
1320 sections.append(TRY(TableSection::parse(section_stream)));
1321 continue;
1322 case MemorySection::section_id:
1323 sections.append(TRY(MemorySection::parse(section_stream)));
1324 continue;
1325 case GlobalSection::section_id:
1326 sections.append(TRY(GlobalSection::parse(section_stream)));
1327 continue;
1328 case ExportSection::section_id:
1329 sections.append(TRY(ExportSection::parse(section_stream)));
1330 continue;
1331 case StartSection::section_id:
1332 sections.append(TRY(StartSection::parse(section_stream)));
1333 continue;
1334 case ElementSection::section_id:
1335 sections.append(TRY(ElementSection::parse(section_stream)));
1336 continue;
1337 case CodeSection::section_id:
1338 sections.append(TRY(CodeSection::parse(section_stream)));
1339 continue;
1340 case DataSection::section_id:
1341 sections.append(TRY(DataSection::parse(section_stream)));
1342 continue;
1343 case DataCountSection::section_id:
1344 sections.append(TRY(DataCountSection::parse(section_stream)));
1345 continue;
1346 default:
1347 return with_eof_check(stream, ParseError::InvalidIndex);
1348 }
1349 }
1350
1351 return Module { move(sections) };
1352}
1353
1354bool Module::populate_sections()
1355{
1356 auto is_ok = true;
1357 FunctionSection const* function_section { nullptr };
1358 for_each_section_of_type<FunctionSection>([&](FunctionSection const& section) { function_section = §ion; });
1359 for_each_section_of_type<CodeSection>([&](CodeSection const& section) {
1360 if (!function_section) {
1361 is_ok = false;
1362 return;
1363 }
1364 size_t index = 0;
1365 for (auto& entry : section.functions()) {
1366 if (function_section->types().size() <= index) {
1367 is_ok = false;
1368 return;
1369 }
1370 auto& type_index = function_section->types()[index];
1371 Vector<ValueType> locals;
1372 for (auto& local : entry.func().locals()) {
1373 for (size_t i = 0; i < local.n(); ++i)
1374 locals.append(local.type());
1375 }
1376 m_functions.empend(type_index, move(locals), entry.func().body());
1377 ++index;
1378 }
1379 });
1380 return is_ok;
1381}
1382
1383DeprecatedString parse_error_to_deprecated_string(ParseError error)
1384{
1385 switch (error) {
1386 case ParseError::UnexpectedEof:
1387 return "Unexpected end-of-file";
1388 case ParseError::ExpectedIndex:
1389 return "Expected a valid index value";
1390 case ParseError::ExpectedKindTag:
1391 return "Expected a valid kind tag";
1392 case ParseError::ExpectedSize:
1393 return "Expected a valid LEB128-encoded size";
1394 case ParseError::ExpectedValueOrTerminator:
1395 return "Expected either a terminator or a value";
1396 case ParseError::InvalidIndex:
1397 return "An index parsed was semantically invalid";
1398 case ParseError::InvalidInput:
1399 return "Input data contained invalid bytes";
1400 case ParseError::InvalidModuleMagic:
1401 return "Incorrect module magic (did not match \\0asm)";
1402 case ParseError::InvalidModuleVersion:
1403 return "Incorrect module version";
1404 case ParseError::InvalidSize:
1405 return "A parsed size did not make sense in context";
1406 case ParseError::InvalidTag:
1407 return "A parsed tag did not make sense in context";
1408 case ParseError::InvalidType:
1409 return "A parsed type did not make sense in context";
1410 case ParseError::NotImplemented:
1411 return "The parser encountered an unimplemented feature";
1412 case ParseError::HugeAllocationRequested:
1413 return "Parsing caused an attempt to allocate a very big chunk of memory, likely malformed data";
1414 case ParseError::OutOfMemory:
1415 return "The parser hit an OOM condition";
1416 case ParseError::ExpectedFloatingImmediate:
1417 return "Expected a floating point immediate";
1418 case ParseError::ExpectedSignedImmediate:
1419 return "Expected a signed integer immediate";
1420 case ParseError::InvalidImmediate:
1421 return "A parsed instruction immediate was invalid for the instruction it was used for";
1422 case ParseError::UnknownInstruction:
1423 return "A parsed instruction was not known to this parser";
1424 }
1425 return "Unknown error";
1426}
1427}