mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 09:02:43 +00:00 
			
		
		
		
	LibWasm: Port the parser to Core::Stream
				
					
				
			This commit is contained in:
		
							parent
							
								
									409fb0fe79
								
							
						
					
					
						commit
						982ebbc304
					
				
					 6 changed files with 292 additions and 263 deletions
				
			
		|  | @ -4,8 +4,7 @@ | ||||||
|  * SPDX-License-Identifier: BSD-2-Clause |  * SPDX-License-Identifier: BSD-2-Clause | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #include <AK/MemoryStream.h> | #include <LibCore/MemoryStream.h> | ||||||
| #include <AK/Stream.h> |  | ||||||
| #include <LibWasm/Types.h> | #include <LibWasm/Types.h> | ||||||
| #include <stddef.h> | #include <stddef.h> | ||||||
| #include <stdint.h> | #include <stdint.h> | ||||||
|  | @ -13,8 +12,10 @@ | ||||||
| extern "C" int LLVMFuzzerTestOneInput(uint8_t const* data, size_t size) | extern "C" int LLVMFuzzerTestOneInput(uint8_t const* data, size_t size) | ||||||
| { | { | ||||||
|     ReadonlyBytes bytes { data, size }; |     ReadonlyBytes bytes { data, size }; | ||||||
|     InputMemoryStream stream { bytes }; |     auto stream_or_error = Core::Stream::FixedMemoryStream::construct(bytes); | ||||||
|     [[maybe_unused]] auto result = Wasm::Module::parse(stream); |     if (stream_or_error.is_error()) | ||||||
|     stream.handle_any_error(); |         return 0; | ||||||
|  |     auto stream = stream_or_error.release_value(); | ||||||
|  |     [[maybe_unused]] auto result = Wasm::Module::parse(*stream); | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -4,6 +4,7 @@ | ||||||
|  * SPDX-License-Identifier: BSD-2-Clause |  * SPDX-License-Identifier: BSD-2-Clause | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
|  | #include <LibCore/MemoryStream.h> | ||||||
| #include <LibCore/Stream.h> | #include <LibCore/Stream.h> | ||||||
| #include <LibTest/JavaScriptTestRunner.h> | #include <LibTest/JavaScriptTestRunner.h> | ||||||
| #include <LibWasm/AbstractMachine/BytecodeInterpreter.h> | #include <LibWasm/AbstractMachine/BytecodeInterpreter.h> | ||||||
|  | @ -105,19 +106,11 @@ TESTJS_GLOBAL_FUNCTION(parse_webassembly_module, parseWebAssemblyModule) | ||||||
|     if (!is<JS::Uint8Array>(object)) |     if (!is<JS::Uint8Array>(object)) | ||||||
|         return vm.throw_completion<JS::TypeError>("Expected a Uint8Array argument to parse_webassembly_module"); |         return vm.throw_completion<JS::TypeError>("Expected a Uint8Array argument to parse_webassembly_module"); | ||||||
|     auto& array = static_cast<JS::Uint8Array&>(*object); |     auto& array = static_cast<JS::Uint8Array&>(*object); | ||||||
|     InputMemoryStream stream { array.data() }; |     auto stream = Core::Stream::FixedMemoryStream::construct(array.data()).release_value_but_fixme_should_propagate_errors(); | ||||||
|     ScopeGuard handle_stream_error { |     auto result = Wasm::Module::parse(*stream); | ||||||
|         [&] { |  | ||||||
|             stream.handle_any_error(); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
|     auto result = Wasm::Module::parse(stream); |  | ||||||
|     if (result.is_error()) |     if (result.is_error()) | ||||||
|         return vm.throw_completion<JS::SyntaxError>(Wasm::parse_error_to_deprecated_string(result.error())); |         return vm.throw_completion<JS::SyntaxError>(Wasm::parse_error_to_deprecated_string(result.error())); | ||||||
| 
 | 
 | ||||||
|     if (stream.handle_any_error()) |  | ||||||
|         return vm.throw_completion<JS::SyntaxError>("Binary stream contained errors"); |  | ||||||
| 
 |  | ||||||
|     HashMap<Wasm::Linker::Name, Wasm::ExternValue> imports; |     HashMap<Wasm::Linker::Name, Wasm::ExternValue> imports; | ||||||
|     auto import_value = vm.argument(1); |     auto import_value = vm.argument(1); | ||||||
|     if (import_value.is_object()) { |     if (import_value.is_object()) { | ||||||
|  |  | ||||||
|  | @ -8,25 +8,27 @@ | ||||||
| #include <AK/LEB128.h> | #include <AK/LEB128.h> | ||||||
| #include <AK/ScopeGuard.h> | #include <AK/ScopeGuard.h> | ||||||
| #include <AK/ScopeLogger.h> | #include <AK/ScopeLogger.h> | ||||||
|  | #include <LibCore/MemoryStream.h> | ||||||
| #include <LibWasm/Types.h> | #include <LibWasm/Types.h> | ||||||
| 
 | 
 | ||||||
| namespace Wasm { | namespace Wasm { | ||||||
| 
 | 
 | ||||||
| ParseError with_eof_check(InputStream const& stream, ParseError error_if_not_eof) | ParseError with_eof_check(Core::Stream::Stream const& stream, ParseError error_if_not_eof) | ||||||
| { | { | ||||||
|     if (stream.unreliable_eof()) |     if (stream.is_eof()) | ||||||
|         return ParseError::UnexpectedEof; |         return ParseError::UnexpectedEof; | ||||||
|     return error_if_not_eof; |     return error_if_not_eof; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| template<typename T> | template<typename T> | ||||||
| static auto parse_vector(InputStream& stream) | static auto parse_vector(Core::Stream::Stream& stream) | ||||||
| { | { | ||||||
|     ScopeLogger<WASM_BINPARSER_DEBUG> logger; |     ScopeLogger<WASM_BINPARSER_DEBUG> logger; | ||||||
|     if constexpr (requires { T::parse(stream); }) { |     if constexpr (requires { T::parse(stream); }) { | ||||||
|         using ResultT = typename decltype(T::parse(stream))::ValueType; |         using ResultT = typename decltype(T::parse(stream))::ValueType; | ||||||
|         size_t count; |         size_t count; | ||||||
|         if (!LEB128::read_unsigned(stream, count)) |         Core::Stream::WrapInAKInputStream wrapped_stream { stream }; | ||||||
|  |         if (!LEB128::read_unsigned(wrapped_stream, count)) | ||||||
|             return ParseResult<Vector<ResultT>> { with_eof_check(stream, ParseError::ExpectedSize) }; |             return ParseResult<Vector<ResultT>> { with_eof_check(stream, ParseError::ExpectedSize) }; | ||||||
| 
 | 
 | ||||||
|         Vector<ResultT> entries; |         Vector<ResultT> entries; | ||||||
|  | @ -39,26 +41,29 @@ static auto parse_vector(InputStream& stream) | ||||||
|         return ParseResult<Vector<ResultT>> { move(entries) }; |         return ParseResult<Vector<ResultT>> { move(entries) }; | ||||||
|     } else { |     } else { | ||||||
|         size_t count; |         size_t count; | ||||||
|         if (!LEB128::read_unsigned(stream, count)) |         Core::Stream::WrapInAKInputStream wrapped_stream { stream }; | ||||||
|  |         if (!LEB128::read_unsigned(wrapped_stream, count)) | ||||||
|             return ParseResult<Vector<T>> { with_eof_check(stream, ParseError::ExpectedSize) }; |             return ParseResult<Vector<T>> { with_eof_check(stream, ParseError::ExpectedSize) }; | ||||||
| 
 | 
 | ||||||
|         Vector<T> entries; |         Vector<T> entries; | ||||||
|         for (size_t i = 0; i < count; ++i) { |         for (size_t i = 0; i < count; ++i) { | ||||||
|             if constexpr (IsSame<T, size_t>) { |             if constexpr (IsSame<T, size_t>) { | ||||||
|                 size_t value; |                 size_t value; | ||||||
|                 if (!LEB128::read_unsigned(stream, value)) |                 Core::Stream::WrapInAKInputStream wrapped_stream { stream }; | ||||||
|  |                 if (!LEB128::read_unsigned(wrapped_stream, value)) | ||||||
|                     return ParseResult<Vector<T>> { with_eof_check(stream, ParseError::ExpectedSize) }; |                     return ParseResult<Vector<T>> { with_eof_check(stream, ParseError::ExpectedSize) }; | ||||||
|                 entries.append(value); |                 entries.append(value); | ||||||
|             } else if constexpr (IsSame<T, ssize_t>) { |             } else if constexpr (IsSame<T, ssize_t>) { | ||||||
|                 ssize_t value; |                 ssize_t value; | ||||||
|                 if (!LEB128::read_signed(stream, value)) |                 Core::Stream::WrapInAKInputStream wrapped_stream { stream }; | ||||||
|  |                 if (!LEB128::read_signed(wrapped_stream, value)) | ||||||
|                     return ParseResult<Vector<T>> { with_eof_check(stream, ParseError::ExpectedSize) }; |                     return ParseResult<Vector<T>> { with_eof_check(stream, ParseError::ExpectedSize) }; | ||||||
|                 entries.append(value); |                 entries.append(value); | ||||||
|             } else if constexpr (IsSame<T, u8>) { |             } else if constexpr (IsSame<T, u8>) { | ||||||
|                 if (count > Constants::max_allowed_vector_size) |                 if (count > Constants::max_allowed_vector_size) | ||||||
|                     return ParseResult<Vector<T>> { ParseError::HugeAllocationRequested }; |                     return ParseResult<Vector<T>> { ParseError::HugeAllocationRequested }; | ||||||
|                 entries.resize(count); |                 entries.resize(count); | ||||||
|                 if (!stream.read_or_error({ entries.data(), entries.size() })) |                 if (stream.read_entire_buffer({ entries.data(), entries.size() }).is_error()) | ||||||
|                     return ParseResult<Vector<T>> { with_eof_check(stream, ParseError::InvalidInput) }; |                     return ParseResult<Vector<T>> { with_eof_check(stream, ParseError::InvalidInput) }; | ||||||
|                 break; // Note: We read this all in one go!
 |                 break; // Note: We read this all in one go!
 | ||||||
|             } |             } | ||||||
|  | @ -67,7 +72,7 @@ static auto parse_vector(InputStream& stream) | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static ParseResult<DeprecatedString> parse_name(InputStream& stream) | static ParseResult<DeprecatedString> parse_name(Core::Stream::Stream& stream) | ||||||
| { | { | ||||||
|     ScopeLogger<WASM_BINPARSER_DEBUG> logger; |     ScopeLogger<WASM_BINPARSER_DEBUG> logger; | ||||||
|     auto data = parse_vector<u8>(stream); |     auto data = parse_vector<u8>(stream); | ||||||
|  | @ -83,24 +88,20 @@ struct ParseUntilAnyOfResult { | ||||||
|     Vector<T> values; |     Vector<T> values; | ||||||
| }; | }; | ||||||
| template<typename T, u8... terminators, typename... Args> | template<typename T, u8... terminators, typename... Args> | ||||||
| static ParseResult<ParseUntilAnyOfResult<T>> parse_until_any_of(InputStream& stream, Args&... args) | static ParseResult<ParseUntilAnyOfResult<T>> parse_until_any_of(Core::Stream::Stream& stream, Args&... args) | ||||||
| requires(requires(InputStream& stream, Args... args) { T::parse(stream, args...); }) | requires(requires(Core::Stream::Stream& stream, Args... args) { T::parse(stream, args...); }) | ||||||
| { | { | ||||||
|     ScopeLogger<WASM_BINPARSER_DEBUG> logger; |     ScopeLogger<WASM_BINPARSER_DEBUG> logger; | ||||||
|     ReconsumableStream new_stream { stream }; |     ReconsumableStream new_stream { stream }; | ||||||
|     ScopeGuard drain_errors { |  | ||||||
|         [&] { |  | ||||||
|             new_stream.handle_any_error(); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| 
 | 
 | ||||||
|     ParseUntilAnyOfResult<T> result; |     ParseUntilAnyOfResult<T> result; | ||||||
|     for (;;) { |     for (;;) { | ||||||
|         u8 byte; |         auto byte_or_error = new_stream.read_value<u8>(); | ||||||
|         new_stream >> byte; |         if (byte_or_error.is_error()) | ||||||
|         if (new_stream.has_any_error()) |  | ||||||
|             return with_eof_check(stream, ParseError::ExpectedValueOrTerminator); |             return with_eof_check(stream, ParseError::ExpectedValueOrTerminator); | ||||||
| 
 | 
 | ||||||
|  |         auto byte = byte_or_error.release_value(); | ||||||
|  | 
 | ||||||
|         constexpr auto equals = [](auto&& a, auto&& b) { return a == b; }; |         constexpr auto equals = [](auto&& a, auto&& b) { return a == b; }; | ||||||
| 
 | 
 | ||||||
|         if ((... || equals(byte, terminators))) { |         if ((... || equals(byte, terminators))) { | ||||||
|  | @ -117,13 +118,15 @@ requires(requires(InputStream& stream, Args... args) { T::parse(stream, args...) | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ParseResult<ValueType> ValueType::parse(InputStream& stream) | ParseResult<ValueType> ValueType::parse(Core::Stream::Stream& stream) | ||||||
| { | { | ||||||
|     ScopeLogger<WASM_BINPARSER_DEBUG> logger("ValueType"sv); |     ScopeLogger<WASM_BINPARSER_DEBUG> logger("ValueType"sv); | ||||||
|     u8 tag; |     auto tag_or_error = stream.read_value<u8>(); | ||||||
|     stream >> tag; |     if (tag_or_error.is_error()) | ||||||
|     if (stream.has_any_error()) |  | ||||||
|         return with_eof_check(stream, ParseError::ExpectedKindTag); |         return with_eof_check(stream, ParseError::ExpectedKindTag); | ||||||
|  | 
 | ||||||
|  |     auto tag = tag_or_error.release_value(); | ||||||
|  | 
 | ||||||
|     switch (tag) { |     switch (tag) { | ||||||
|     case Constants::i32_tag: |     case Constants::i32_tag: | ||||||
|         return ValueType(I32); |         return ValueType(I32); | ||||||
|  | @ -142,7 +145,7 @@ ParseResult<ValueType> ValueType::parse(InputStream& stream) | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ParseResult<ResultType> ResultType::parse(InputStream& stream) | ParseResult<ResultType> ResultType::parse(Core::Stream::Stream& stream) | ||||||
| { | { | ||||||
|     ScopeLogger<WASM_BINPARSER_DEBUG> logger("ResultType"sv); |     ScopeLogger<WASM_BINPARSER_DEBUG> logger("ResultType"sv); | ||||||
|     auto types = parse_vector<ValueType>(stream); |     auto types = parse_vector<ValueType>(stream); | ||||||
|  | @ -151,14 +154,15 @@ ParseResult<ResultType> ResultType::parse(InputStream& stream) | ||||||
|     return ResultType { types.release_value() }; |     return ResultType { types.release_value() }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ParseResult<FunctionType> FunctionType::parse(InputStream& stream) | ParseResult<FunctionType> FunctionType::parse(Core::Stream::Stream& stream) | ||||||
| { | { | ||||||
|     ScopeLogger<WASM_BINPARSER_DEBUG> logger("FunctionType"sv); |     ScopeLogger<WASM_BINPARSER_DEBUG> logger("FunctionType"sv); | ||||||
|     u8 tag; |     auto tag_or_error = stream.read_value<u8>(); | ||||||
|     stream >> tag; |     if (tag_or_error.is_error()) | ||||||
|     if (stream.has_any_error()) |  | ||||||
|         return with_eof_check(stream, ParseError::ExpectedKindTag); |         return with_eof_check(stream, ParseError::ExpectedKindTag); | ||||||
| 
 | 
 | ||||||
|  |     auto tag = tag_or_error.release_value(); | ||||||
|  | 
 | ||||||
|     if (tag != Constants::function_signature_tag) { |     if (tag != Constants::function_signature_tag) { | ||||||
|         dbgln("Expected 0x60, but found {:#x}", tag); |         dbgln("Expected 0x60, but found {:#x}", tag); | ||||||
|         return with_eof_check(stream, ParseError::InvalidTag); |         return with_eof_check(stream, ParseError::InvalidTag); | ||||||
|  | @ -174,25 +178,28 @@ ParseResult<FunctionType> FunctionType::parse(InputStream& stream) | ||||||
|     return FunctionType { parameters_result.release_value(), results_result.release_value() }; |     return FunctionType { parameters_result.release_value(), results_result.release_value() }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ParseResult<Limits> Limits::parse(InputStream& stream) | ParseResult<Limits> Limits::parse(Core::Stream::Stream& stream) | ||||||
| { | { | ||||||
|     ScopeLogger<WASM_BINPARSER_DEBUG> logger("Limits"sv); |     ScopeLogger<WASM_BINPARSER_DEBUG> logger("Limits"sv); | ||||||
|     u8 flag; |     auto flag_or_error = stream.read_value<u8>(); | ||||||
|     stream >> flag; |     if (flag_or_error.is_error()) | ||||||
|     if (stream.has_any_error()) |  | ||||||
|         return with_eof_check(stream, ParseError::ExpectedKindTag); |         return with_eof_check(stream, ParseError::ExpectedKindTag); | ||||||
| 
 | 
 | ||||||
|  |     auto flag = flag_or_error.release_value(); | ||||||
|  | 
 | ||||||
|     if (flag > 1) |     if (flag > 1) | ||||||
|         return with_eof_check(stream, ParseError::InvalidTag); |         return with_eof_check(stream, ParseError::InvalidTag); | ||||||
| 
 | 
 | ||||||
|     size_t min; |     size_t min; | ||||||
|     if (!LEB128::read_unsigned(stream, min)) |     Core::Stream::WrapInAKInputStream wrapped_stream { stream }; | ||||||
|  |     if (!LEB128::read_unsigned(wrapped_stream, min)) | ||||||
|         return with_eof_check(stream, ParseError::ExpectedSize); |         return with_eof_check(stream, ParseError::ExpectedSize); | ||||||
| 
 | 
 | ||||||
|     Optional<u32> max; |     Optional<u32> max; | ||||||
|     if (flag) { |     if (flag) { | ||||||
|         size_t value; |         size_t value; | ||||||
|         if (!LEB128::read_unsigned(stream, value)) |         Core::Stream::WrapInAKInputStream wrapped_stream { stream }; | ||||||
|  |         if (!LEB128::read_unsigned(wrapped_stream, value)) | ||||||
|             return with_eof_check(stream, ParseError::ExpectedSize); |             return with_eof_check(stream, ParseError::ExpectedSize); | ||||||
|         max = value; |         max = value; | ||||||
|     } |     } | ||||||
|  | @ -200,7 +207,7 @@ ParseResult<Limits> Limits::parse(InputStream& stream) | ||||||
|     return Limits { static_cast<u32>(min), move(max) }; |     return Limits { static_cast<u32>(min), move(max) }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ParseResult<MemoryType> MemoryType::parse(InputStream& stream) | ParseResult<MemoryType> MemoryType::parse(Core::Stream::Stream& stream) | ||||||
| { | { | ||||||
|     ScopeLogger<WASM_BINPARSER_DEBUG> logger("MemoryType"sv); |     ScopeLogger<WASM_BINPARSER_DEBUG> logger("MemoryType"sv); | ||||||
|     auto limits_result = Limits::parse(stream); |     auto limits_result = Limits::parse(stream); | ||||||
|  | @ -209,7 +216,7 @@ ParseResult<MemoryType> MemoryType::parse(InputStream& stream) | ||||||
|     return MemoryType { limits_result.release_value() }; |     return MemoryType { limits_result.release_value() }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ParseResult<TableType> TableType::parse(InputStream& stream) | ParseResult<TableType> TableType::parse(Core::Stream::Stream& stream) | ||||||
| { | { | ||||||
|     ScopeLogger<WASM_BINPARSER_DEBUG> logger("TableType"sv); |     ScopeLogger<WASM_BINPARSER_DEBUG> logger("TableType"sv); | ||||||
|     auto type_result = ValueType::parse(stream); |     auto type_result = ValueType::parse(stream); | ||||||
|  | @ -223,50 +230,48 @@ ParseResult<TableType> TableType::parse(InputStream& stream) | ||||||
|     return TableType { type_result.release_value(), limits_result.release_value() }; |     return TableType { type_result.release_value(), limits_result.release_value() }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ParseResult<GlobalType> GlobalType::parse(InputStream& stream) | ParseResult<GlobalType> GlobalType::parse(Core::Stream::Stream& stream) | ||||||
| { | { | ||||||
|     ScopeLogger<WASM_BINPARSER_DEBUG> logger("GlobalType"sv); |     ScopeLogger<WASM_BINPARSER_DEBUG> logger("GlobalType"sv); | ||||||
|     auto type_result = ValueType::parse(stream); |     auto type_result = ValueType::parse(stream); | ||||||
|     if (type_result.is_error()) |     if (type_result.is_error()) | ||||||
|         return type_result.error(); |         return type_result.error(); | ||||||
|     u8 mutable_; |  | ||||||
|     stream >> mutable_; |  | ||||||
| 
 | 
 | ||||||
|     if (stream.has_any_error()) |     auto mutable_or_error = stream.read_value<u8>(); | ||||||
|  |     if (mutable_or_error.is_error()) | ||||||
|         return with_eof_check(stream, ParseError::ExpectedKindTag); |         return with_eof_check(stream, ParseError::ExpectedKindTag); | ||||||
| 
 | 
 | ||||||
|  |     auto mutable_ = mutable_or_error.release_value(); | ||||||
|  | 
 | ||||||
|     if (mutable_ > 1) |     if (mutable_ > 1) | ||||||
|         return with_eof_check(stream, ParseError::InvalidTag); |         return with_eof_check(stream, ParseError::InvalidTag); | ||||||
| 
 | 
 | ||||||
|     return GlobalType { type_result.release_value(), mutable_ == 0x01 }; |     return GlobalType { type_result.release_value(), mutable_ == 0x01 }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ParseResult<BlockType> BlockType::parse(InputStream& stream) | ParseResult<BlockType> BlockType::parse(Core::Stream::Stream& stream) | ||||||
| { | { | ||||||
|     ScopeLogger<WASM_BINPARSER_DEBUG> logger("BlockType"sv); |     ScopeLogger<WASM_BINPARSER_DEBUG> logger("BlockType"sv); | ||||||
|     u8 kind; |     auto kind_or_error = stream.read_value<u8>(); | ||||||
|     stream >> kind; |     if (kind_or_error.is_error()) | ||||||
|     if (stream.has_any_error()) |  | ||||||
|         return with_eof_check(stream, ParseError::ExpectedKindTag); |         return with_eof_check(stream, ParseError::ExpectedKindTag); | ||||||
|  | 
 | ||||||
|  |     auto kind = kind_or_error.release_value(); | ||||||
|     if (kind == Constants::empty_block_tag) |     if (kind == Constants::empty_block_tag) | ||||||
|         return BlockType {}; |         return BlockType {}; | ||||||
| 
 | 
 | ||||||
|     { |     { | ||||||
|         InputMemoryStream value_stream { ReadonlyBytes { &kind, 1 } }; |         auto value_stream = Core::Stream::FixedMemoryStream::construct(ReadonlyBytes { &kind, 1 }).release_value_but_fixme_should_propagate_errors(); | ||||||
|         if (auto value_type = ValueType::parse(value_stream); !value_type.is_error()) |         if (auto value_type = ValueType::parse(*value_stream); !value_type.is_error()) | ||||||
|             return BlockType { value_type.release_value() }; |             return BlockType { value_type.release_value() }; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     ReconsumableStream new_stream { stream }; |     ReconsumableStream new_stream { stream }; | ||||||
|     new_stream.unread({ &kind, 1 }); |     new_stream.unread({ &kind, 1 }); | ||||||
|     ScopeGuard drain_errors { |  | ||||||
|         [&] { |  | ||||||
|             new_stream.handle_any_error(); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| 
 | 
 | ||||||
|     ssize_t index_value; |     ssize_t index_value; | ||||||
|     if (!LEB128::read_signed(new_stream, index_value)) |     Core::Stream::WrapInAKInputStream wrapped_new_stream { new_stream }; | ||||||
|  |     if (!LEB128::read_signed(wrapped_new_stream, index_value)) | ||||||
|         return with_eof_check(stream, ParseError::ExpectedIndex); |         return with_eof_check(stream, ParseError::ExpectedIndex); | ||||||
| 
 | 
 | ||||||
|     if (index_value < 0) { |     if (index_value < 0) { | ||||||
|  | @ -277,7 +282,7 @@ ParseResult<BlockType> BlockType::parse(InputStream& stream) | ||||||
|     return BlockType { TypeIndex(index_value) }; |     return BlockType { TypeIndex(index_value) }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ParseResult<Vector<Instruction>> Instruction::parse(InputStream& stream, InstructionPointer& ip) | ParseResult<Vector<Instruction>> Instruction::parse(Core::Stream::Stream& stream, InstructionPointer& ip) | ||||||
| { | { | ||||||
|     struct NestedInstructionState { |     struct NestedInstructionState { | ||||||
|         Vector<Instruction> prior_instructions; |         Vector<Instruction> prior_instructions; | ||||||
|  | @ -291,11 +296,12 @@ ParseResult<Vector<Instruction>> Instruction::parse(InputStream& stream, Instruc | ||||||
| 
 | 
 | ||||||
|     do { |     do { | ||||||
|         ScopeLogger<WASM_BINPARSER_DEBUG> logger("Instruction"sv); |         ScopeLogger<WASM_BINPARSER_DEBUG> logger("Instruction"sv); | ||||||
|         u8 byte; |         auto byte_or_error = stream.read_value<u8>(); | ||||||
|         stream >> byte; |         if (byte_or_error.is_error()) | ||||||
|         if (stream.has_any_error()) |  | ||||||
|             return with_eof_check(stream, ParseError::ExpectedKindTag); |             return with_eof_check(stream, ParseError::ExpectedKindTag); | ||||||
| 
 | 
 | ||||||
|  |         auto byte = byte_or_error.release_value(); | ||||||
|  | 
 | ||||||
|         if (!nested_instructions.is_empty()) { |         if (!nested_instructions.is_empty()) { | ||||||
|             auto& nested_structure = nested_instructions.last(); |             auto& nested_structure = nested_instructions.last(); | ||||||
|             if (byte == 0x0b) { |             if (byte == 0x0b) { | ||||||
|  | @ -408,13 +414,15 @@ ParseResult<Vector<Instruction>> Instruction::parse(InputStream& stream, Instruc | ||||||
|         case Instructions::i64_store8.value(): |         case Instructions::i64_store8.value(): | ||||||
|         case Instructions::i64_store16.value(): |         case Instructions::i64_store16.value(): | ||||||
|         case Instructions::i64_store32.value(): { |         case Instructions::i64_store32.value(): { | ||||||
|  |             Core::Stream::WrapInAKInputStream wrapped_stream { stream }; | ||||||
|  | 
 | ||||||
|             // op (align offset)
 |             // op (align offset)
 | ||||||
|             size_t align; |             size_t align; | ||||||
|             if (!LEB128::read_unsigned(stream, align)) |             if (!LEB128::read_unsigned(wrapped_stream, align)) | ||||||
|                 return with_eof_check(stream, ParseError::InvalidInput); |                 return with_eof_check(stream, ParseError::InvalidInput); | ||||||
| 
 | 
 | ||||||
|             size_t offset; |             size_t offset; | ||||||
|             if (!LEB128::read_unsigned(stream, offset)) |             if (!LEB128::read_unsigned(wrapped_stream, offset)) | ||||||
|                 return with_eof_check(stream, ParseError::InvalidInput); |                 return with_eof_check(stream, ParseError::InvalidInput); | ||||||
| 
 | 
 | ||||||
|             resulting_instructions.append(Instruction { opcode, MemoryArgument { static_cast<u32>(align), static_cast<u32>(offset) } }); |             resulting_instructions.append(Instruction { opcode, MemoryArgument { static_cast<u32>(align), static_cast<u32>(offset) } }); | ||||||
|  | @ -443,10 +451,11 @@ ParseResult<Vector<Instruction>> Instruction::parse(InputStream& stream, Instruc | ||||||
|         case Instructions::memory_grow.value(): { |         case Instructions::memory_grow.value(): { | ||||||
|             // op 0x0
 |             // op 0x0
 | ||||||
|             // The zero is currently unused.
 |             // The zero is currently unused.
 | ||||||
|             u8 unused; |             auto unused_or_error = stream.read_value<u8>(); | ||||||
|             stream >> unused; |             if (unused_or_error.is_error()) | ||||||
|             if (stream.has_any_error()) |  | ||||||
|                 return with_eof_check(stream, ParseError::ExpectedKindTag); |                 return with_eof_check(stream, ParseError::ExpectedKindTag); | ||||||
|  | 
 | ||||||
|  |             auto unused = unused_or_error.release_value(); | ||||||
|             if (unused != 0x00) { |             if (unused != 0x00) { | ||||||
|                 dbgln("Invalid tag in memory_grow {}", unused); |                 dbgln("Invalid tag in memory_grow {}", unused); | ||||||
|                 return with_eof_check(stream, ParseError::InvalidTag); |                 return with_eof_check(stream, ParseError::InvalidTag); | ||||||
|  | @ -457,7 +466,8 @@ ParseResult<Vector<Instruction>> Instruction::parse(InputStream& stream, Instruc | ||||||
|         } |         } | ||||||
|         case Instructions::i32_const.value(): { |         case Instructions::i32_const.value(): { | ||||||
|             i32 value; |             i32 value; | ||||||
|             if (!LEB128::read_signed(stream, value)) |             Core::Stream::WrapInAKInputStream wrapped_stream { stream }; | ||||||
|  |             if (!LEB128::read_signed(wrapped_stream, value)) | ||||||
|                 return with_eof_check(stream, ParseError::ExpectedSignedImmediate); |                 return with_eof_check(stream, ParseError::ExpectedSignedImmediate); | ||||||
| 
 | 
 | ||||||
|             resulting_instructions.append(Instruction { opcode, value }); |             resulting_instructions.append(Instruction { opcode, value }); | ||||||
|  | @ -466,7 +476,8 @@ ParseResult<Vector<Instruction>> Instruction::parse(InputStream& stream, Instruc | ||||||
|         case Instructions::i64_const.value(): { |         case Instructions::i64_const.value(): { | ||||||
|             // op literal
 |             // op literal
 | ||||||
|             i64 value; |             i64 value; | ||||||
|             if (!LEB128::read_signed(stream, value)) |             Core::Stream::WrapInAKInputStream wrapped_stream { stream }; | ||||||
|  |             if (!LEB128::read_signed(wrapped_stream, value)) | ||||||
|                 return with_eof_check(stream, ParseError::ExpectedSignedImmediate); |                 return with_eof_check(stream, ParseError::ExpectedSignedImmediate); | ||||||
| 
 | 
 | ||||||
|             resulting_instructions.append(Instruction { opcode, value }); |             resulting_instructions.append(Instruction { opcode, value }); | ||||||
|  | @ -475,8 +486,7 @@ ParseResult<Vector<Instruction>> Instruction::parse(InputStream& stream, Instruc | ||||||
|         case Instructions::f32_const.value(): { |         case Instructions::f32_const.value(): { | ||||||
|             // op literal
 |             // op literal
 | ||||||
|             LittleEndian<u32> value; |             LittleEndian<u32> value; | ||||||
|             stream >> value; |             if (stream.read_entire_buffer(value.bytes()).is_error()) | ||||||
|             if (stream.has_any_error()) |  | ||||||
|                 return with_eof_check(stream, ParseError::ExpectedFloatingImmediate); |                 return with_eof_check(stream, ParseError::ExpectedFloatingImmediate); | ||||||
| 
 | 
 | ||||||
|             auto floating = bit_cast<float>(static_cast<u32>(value)); |             auto floating = bit_cast<float>(static_cast<u32>(value)); | ||||||
|  | @ -486,8 +496,7 @@ ParseResult<Vector<Instruction>> Instruction::parse(InputStream& stream, Instruc | ||||||
|         case Instructions::f64_const.value(): { |         case Instructions::f64_const.value(): { | ||||||
|             // op literal
 |             // op literal
 | ||||||
|             LittleEndian<u64> value; |             LittleEndian<u64> value; | ||||||
|             stream >> value; |             if (stream.read_entire_buffer(value.bytes()).is_error()) | ||||||
|             if (stream.has_any_error()) |  | ||||||
|                 return with_eof_check(stream, ParseError::ExpectedFloatingImmediate); |                 return with_eof_check(stream, ParseError::ExpectedFloatingImmediate); | ||||||
| 
 | 
 | ||||||
|             auto floating = bit_cast<double>(static_cast<u64>(value)); |             auto floating = bit_cast<double>(static_cast<u64>(value)); | ||||||
|  | @ -668,7 +677,8 @@ ParseResult<Vector<Instruction>> Instruction::parse(InputStream& stream, Instruc | ||||||
|         case 0xfc: { |         case 0xfc: { | ||||||
|             // These are multibyte instructions.
 |             // These are multibyte instructions.
 | ||||||
|             u32 selector; |             u32 selector; | ||||||
|             if (!LEB128::read_unsigned(stream, selector)) |             Core::Stream::WrapInAKInputStream wrapped_stream { stream }; | ||||||
|  |             if (!LEB128::read_unsigned(wrapped_stream, selector)) | ||||||
|                 return with_eof_check(stream, ParseError::InvalidInput); |                 return with_eof_check(stream, ParseError::InvalidInput); | ||||||
|             switch (selector) { |             switch (selector) { | ||||||
|             case Instructions::i32_trunc_sat_f32_s_second: |             case Instructions::i32_trunc_sat_f32_s_second: | ||||||
|  | @ -685,10 +695,11 @@ ParseResult<Vector<Instruction>> Instruction::parse(InputStream& stream, Instruc | ||||||
|                 auto index = GenericIndexParser<DataIndex>::parse(stream); |                 auto index = GenericIndexParser<DataIndex>::parse(stream); | ||||||
|                 if (index.is_error()) |                 if (index.is_error()) | ||||||
|                     return index.error(); |                     return index.error(); | ||||||
|                 u8 unused; |                 auto unused_or_error = stream.read_value<u8>(); | ||||||
|                 stream >> unused; |                 if (unused_or_error.is_error()) | ||||||
|                 if (stream.has_any_error()) |  | ||||||
|                     return with_eof_check(stream, ParseError::InvalidInput); |                     return with_eof_check(stream, ParseError::InvalidInput); | ||||||
|  | 
 | ||||||
|  |                 auto unused = unused_or_error.release_value(); | ||||||
|                 if (unused != 0x00) |                 if (unused != 0x00) | ||||||
|                     return ParseError::InvalidImmediate; |                     return ParseError::InvalidImmediate; | ||||||
|                 resulting_instructions.append(Instruction { OpCode { 0xfc00 | selector }, index.release_value() }); |                 resulting_instructions.append(Instruction { OpCode { 0xfc00 | selector }, index.release_value() }); | ||||||
|  | @ -703,10 +714,11 @@ ParseResult<Vector<Instruction>> Instruction::parse(InputStream& stream, Instruc | ||||||
|             } |             } | ||||||
|             case Instructions::memory_copy_second: { |             case Instructions::memory_copy_second: { | ||||||
|                 for (size_t i = 0; i < 2; ++i) { |                 for (size_t i = 0; i < 2; ++i) { | ||||||
|                     u8 unused; |                     auto unused_or_error = stream.read_value<u8>(); | ||||||
|                     stream >> unused; |                     if (unused_or_error.is_error()) | ||||||
|                     if (stream.has_any_error()) |  | ||||||
|                         return with_eof_check(stream, ParseError::InvalidInput); |                         return with_eof_check(stream, ParseError::InvalidInput); | ||||||
|  | 
 | ||||||
|  |                     auto unused = unused_or_error.release_value(); | ||||||
|                     if (unused != 0x00) |                     if (unused != 0x00) | ||||||
|                         return ParseError::InvalidImmediate; |                         return ParseError::InvalidImmediate; | ||||||
|                 } |                 } | ||||||
|  | @ -714,10 +726,11 @@ ParseResult<Vector<Instruction>> Instruction::parse(InputStream& stream, Instruc | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|             case Instructions::memory_fill_second: { |             case Instructions::memory_fill_second: { | ||||||
|                 u8 unused; |                 auto unused_or_error = stream.read_value<u8>(); | ||||||
|                 stream >> unused; |                 if (unused_or_error.is_error()) | ||||||
|                 if (stream.has_any_error()) |  | ||||||
|                     return with_eof_check(stream, ParseError::InvalidInput); |                     return with_eof_check(stream, ParseError::InvalidInput); | ||||||
|  | 
 | ||||||
|  |                 auto unused = unused_or_error.release_value(); | ||||||
|                 if (unused != 0x00) |                 if (unused != 0x00) | ||||||
|                     return ParseError::InvalidImmediate; |                     return ParseError::InvalidImmediate; | ||||||
|                 resulting_instructions.append(Instruction { OpCode { 0xfc00 | selector } }); |                 resulting_instructions.append(Instruction { OpCode { 0xfc00 | selector } }); | ||||||
|  | @ -769,7 +782,7 @@ ParseResult<Vector<Instruction>> Instruction::parse(InputStream& stream, Instruc | ||||||
|     return resulting_instructions; |     return resulting_instructions; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ParseResult<CustomSection> CustomSection::parse(InputStream& stream) | ParseResult<CustomSection> CustomSection::parse(Core::Stream::Stream& stream) | ||||||
| { | { | ||||||
|     ScopeLogger<WASM_BINPARSER_DEBUG> logger("CustomSection"sv); |     ScopeLogger<WASM_BINPARSER_DEBUG> logger("CustomSection"sv); | ||||||
|     auto name = parse_name(stream); |     auto name = parse_name(stream); | ||||||
|  | @ -780,9 +793,12 @@ ParseResult<CustomSection> CustomSection::parse(InputStream& stream) | ||||||
|     if (data_buffer.try_resize(64).is_error()) |     if (data_buffer.try_resize(64).is_error()) | ||||||
|         return ParseError::OutOfMemory; |         return ParseError::OutOfMemory; | ||||||
| 
 | 
 | ||||||
|     while (!stream.has_any_error() && !stream.unreliable_eof()) { |     while (!stream.is_eof()) { | ||||||
|         char buf[16]; |         char buf[16]; | ||||||
|         auto size = stream.read({ buf, 16 }); |         auto span_or_error = stream.read({ buf, 16 }); | ||||||
|  |         if (span_or_error.is_error()) | ||||||
|  |             break; | ||||||
|  |         auto size = span_or_error.release_value().size(); | ||||||
|         if (size == 0) |         if (size == 0) | ||||||
|             break; |             break; | ||||||
|         if (data_buffer.try_append(buf, size).is_error()) |         if (data_buffer.try_append(buf, size).is_error()) | ||||||
|  | @ -792,7 +808,7 @@ ParseResult<CustomSection> CustomSection::parse(InputStream& stream) | ||||||
|     return CustomSection(name.release_value(), move(data_buffer)); |     return CustomSection(name.release_value(), move(data_buffer)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ParseResult<TypeSection> TypeSection::parse(InputStream& stream) | ParseResult<TypeSection> TypeSection::parse(Core::Stream::Stream& stream) | ||||||
| { | { | ||||||
|     ScopeLogger<WASM_BINPARSER_DEBUG> logger("TypeSection"sv); |     ScopeLogger<WASM_BINPARSER_DEBUG> logger("TypeSection"sv); | ||||||
|     auto types = parse_vector<FunctionType>(stream); |     auto types = parse_vector<FunctionType>(stream); | ||||||
|  | @ -801,7 +817,7 @@ ParseResult<TypeSection> TypeSection::parse(InputStream& stream) | ||||||
|     return TypeSection { types.release_value() }; |     return TypeSection { types.release_value() }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ParseResult<ImportSection::Import> ImportSection::Import::parse(InputStream& stream) | ParseResult<ImportSection::Import> ImportSection::Import::parse(Core::Stream::Stream& stream) | ||||||
| { | { | ||||||
|     ScopeLogger<WASM_BINPARSER_DEBUG> logger("Import"sv); |     ScopeLogger<WASM_BINPARSER_DEBUG> logger("Import"sv); | ||||||
|     auto module = parse_name(stream); |     auto module = parse_name(stream); | ||||||
|  | @ -810,11 +826,12 @@ ParseResult<ImportSection::Import> ImportSection::Import::parse(InputStream& str | ||||||
|     auto name = parse_name(stream); |     auto name = parse_name(stream); | ||||||
|     if (name.is_error()) |     if (name.is_error()) | ||||||
|         return name.error(); |         return name.error(); | ||||||
|     u8 tag; |     auto tag_or_error = stream.read_value<u8>(); | ||||||
|     stream >> tag; |     if (tag_or_error.is_error()) | ||||||
|     if (stream.has_any_error()) |  | ||||||
|         return with_eof_check(stream, ParseError::ExpectedKindTag); |         return with_eof_check(stream, ParseError::ExpectedKindTag); | ||||||
| 
 | 
 | ||||||
|  |     auto tag = tag_or_error.release_value(); | ||||||
|  | 
 | ||||||
|     switch (tag) { |     switch (tag) { | ||||||
|     case Constants::extern_function_tag: { |     case Constants::extern_function_tag: { | ||||||
|         auto index = GenericIndexParser<TypeIndex>::parse(stream); |         auto index = GenericIndexParser<TypeIndex>::parse(stream); | ||||||
|  | @ -833,7 +850,7 @@ ParseResult<ImportSection::Import> ImportSection::Import::parse(InputStream& str | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ParseResult<ImportSection> ImportSection::parse(InputStream& stream) | ParseResult<ImportSection> ImportSection::parse(Core::Stream::Stream& stream) | ||||||
| { | { | ||||||
|     ScopeLogger<WASM_BINPARSER_DEBUG> logger("ImportSection"sv); |     ScopeLogger<WASM_BINPARSER_DEBUG> logger("ImportSection"sv); | ||||||
|     auto imports = parse_vector<Import>(stream); |     auto imports = parse_vector<Import>(stream); | ||||||
|  | @ -842,7 +859,7 @@ ParseResult<ImportSection> ImportSection::parse(InputStream& stream) | ||||||
|     return ImportSection { imports.release_value() }; |     return ImportSection { imports.release_value() }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ParseResult<FunctionSection> FunctionSection::parse(InputStream& stream) | ParseResult<FunctionSection> FunctionSection::parse(Core::Stream::Stream& stream) | ||||||
| { | { | ||||||
|     ScopeLogger<WASM_BINPARSER_DEBUG> logger("FunctionSection"sv); |     ScopeLogger<WASM_BINPARSER_DEBUG> logger("FunctionSection"sv); | ||||||
|     auto indices = parse_vector<size_t>(stream); |     auto indices = parse_vector<size_t>(stream); | ||||||
|  | @ -857,7 +874,7 @@ ParseResult<FunctionSection> FunctionSection::parse(InputStream& stream) | ||||||
|     return FunctionSection { move(typed_indices) }; |     return FunctionSection { move(typed_indices) }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ParseResult<TableSection::Table> TableSection::Table::parse(InputStream& stream) | ParseResult<TableSection::Table> TableSection::Table::parse(Core::Stream::Stream& stream) | ||||||
| { | { | ||||||
|     ScopeLogger<WASM_BINPARSER_DEBUG> logger("Table"sv); |     ScopeLogger<WASM_BINPARSER_DEBUG> logger("Table"sv); | ||||||
|     auto type = TableType::parse(stream); |     auto type = TableType::parse(stream); | ||||||
|  | @ -866,7 +883,7 @@ ParseResult<TableSection::Table> TableSection::Table::parse(InputStream& stream) | ||||||
|     return Table { type.release_value() }; |     return Table { type.release_value() }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ParseResult<TableSection> TableSection::parse(InputStream& stream) | ParseResult<TableSection> TableSection::parse(Core::Stream::Stream& stream) | ||||||
| { | { | ||||||
|     ScopeLogger<WASM_BINPARSER_DEBUG> logger("TableSection"sv); |     ScopeLogger<WASM_BINPARSER_DEBUG> logger("TableSection"sv); | ||||||
|     auto tables = parse_vector<Table>(stream); |     auto tables = parse_vector<Table>(stream); | ||||||
|  | @ -875,7 +892,7 @@ ParseResult<TableSection> TableSection::parse(InputStream& stream) | ||||||
|     return TableSection { tables.release_value() }; |     return TableSection { tables.release_value() }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ParseResult<MemorySection::Memory> MemorySection::Memory::parse(InputStream& stream) | ParseResult<MemorySection::Memory> MemorySection::Memory::parse(Core::Stream::Stream& stream) | ||||||
| { | { | ||||||
|     ScopeLogger<WASM_BINPARSER_DEBUG> logger("Memory"sv); |     ScopeLogger<WASM_BINPARSER_DEBUG> logger("Memory"sv); | ||||||
|     auto type = MemoryType::parse(stream); |     auto type = MemoryType::parse(stream); | ||||||
|  | @ -884,7 +901,7 @@ ParseResult<MemorySection::Memory> MemorySection::Memory::parse(InputStream& str | ||||||
|     return Memory { type.release_value() }; |     return Memory { type.release_value() }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ParseResult<MemorySection> MemorySection::parse(InputStream& stream) | ParseResult<MemorySection> MemorySection::parse(Core::Stream::Stream& stream) | ||||||
| { | { | ||||||
|     ScopeLogger<WASM_BINPARSER_DEBUG> logger("MemorySection"sv); |     ScopeLogger<WASM_BINPARSER_DEBUG> logger("MemorySection"sv); | ||||||
|     auto memories = parse_vector<Memory>(stream); |     auto memories = parse_vector<Memory>(stream); | ||||||
|  | @ -893,7 +910,7 @@ ParseResult<MemorySection> MemorySection::parse(InputStream& stream) | ||||||
|     return MemorySection { memories.release_value() }; |     return MemorySection { memories.release_value() }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ParseResult<Expression> Expression::parse(InputStream& stream) | ParseResult<Expression> Expression::parse(Core::Stream::Stream& stream) | ||||||
| { | { | ||||||
|     ScopeLogger<WASM_BINPARSER_DEBUG> logger("Expression"sv); |     ScopeLogger<WASM_BINPARSER_DEBUG> logger("Expression"sv); | ||||||
|     InstructionPointer ip { 0 }; |     InstructionPointer ip { 0 }; | ||||||
|  | @ -904,7 +921,7 @@ ParseResult<Expression> Expression::parse(InputStream& stream) | ||||||
|     return Expression { move(instructions.value().values) }; |     return Expression { move(instructions.value().values) }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ParseResult<GlobalSection::Global> GlobalSection::Global::parse(InputStream& stream) | ParseResult<GlobalSection::Global> GlobalSection::Global::parse(Core::Stream::Stream& stream) | ||||||
| { | { | ||||||
|     ScopeLogger<WASM_BINPARSER_DEBUG> logger("Global"sv); |     ScopeLogger<WASM_BINPARSER_DEBUG> logger("Global"sv); | ||||||
|     auto type = GlobalType::parse(stream); |     auto type = GlobalType::parse(stream); | ||||||
|  | @ -916,7 +933,7 @@ ParseResult<GlobalSection::Global> GlobalSection::Global::parse(InputStream& str | ||||||
|     return Global { type.release_value(), exprs.release_value() }; |     return Global { type.release_value(), exprs.release_value() }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ParseResult<GlobalSection> GlobalSection::parse(InputStream& stream) | ParseResult<GlobalSection> GlobalSection::parse(Core::Stream::Stream& stream) | ||||||
| { | { | ||||||
|     ScopeLogger<WASM_BINPARSER_DEBUG> logger("GlobalSection"sv); |     ScopeLogger<WASM_BINPARSER_DEBUG> logger("GlobalSection"sv); | ||||||
|     auto result = parse_vector<Global>(stream); |     auto result = parse_vector<Global>(stream); | ||||||
|  | @ -925,19 +942,21 @@ ParseResult<GlobalSection> GlobalSection::parse(InputStream& stream) | ||||||
|     return GlobalSection { result.release_value() }; |     return GlobalSection { result.release_value() }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ParseResult<ExportSection::Export> ExportSection::Export::parse(InputStream& stream) | ParseResult<ExportSection::Export> ExportSection::Export::parse(Core::Stream::Stream& stream) | ||||||
| { | { | ||||||
|     ScopeLogger<WASM_BINPARSER_DEBUG> logger("Export"sv); |     ScopeLogger<WASM_BINPARSER_DEBUG> logger("Export"sv); | ||||||
|     auto name = parse_name(stream); |     auto name = parse_name(stream); | ||||||
|     if (name.is_error()) |     if (name.is_error()) | ||||||
|         return name.error(); |         return name.error(); | ||||||
|     u8 tag; |     auto tag_or_error = stream.read_value<u8>(); | ||||||
|     stream >> tag; |     if (tag_or_error.is_error()) | ||||||
|     if (stream.has_any_error()) |  | ||||||
|         return with_eof_check(stream, ParseError::ExpectedKindTag); |         return with_eof_check(stream, ParseError::ExpectedKindTag); | ||||||
| 
 | 
 | ||||||
|  |     auto tag = tag_or_error.release_value(); | ||||||
|  | 
 | ||||||
|     size_t index; |     size_t index; | ||||||
|     if (!LEB128::read_unsigned(stream, index)) |     Core::Stream::WrapInAKInputStream wrapped_stream { stream }; | ||||||
|  |     if (!LEB128::read_unsigned(wrapped_stream, index)) | ||||||
|         return with_eof_check(stream, ParseError::ExpectedIndex); |         return with_eof_check(stream, ParseError::ExpectedIndex); | ||||||
| 
 | 
 | ||||||
|     switch (tag) { |     switch (tag) { | ||||||
|  | @ -954,7 +973,7 @@ ParseResult<ExportSection::Export> ExportSection::Export::parse(InputStream& str | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ParseResult<ExportSection> ExportSection::parse(InputStream& stream) | ParseResult<ExportSection> ExportSection::parse(Core::Stream::Stream& stream) | ||||||
| { | { | ||||||
|     ScopeLogger<WASM_BINPARSER_DEBUG> logger("ExportSection"sv); |     ScopeLogger<WASM_BINPARSER_DEBUG> logger("ExportSection"sv); | ||||||
|     auto result = parse_vector<Export>(stream); |     auto result = parse_vector<Export>(stream); | ||||||
|  | @ -963,7 +982,7 @@ ParseResult<ExportSection> ExportSection::parse(InputStream& stream) | ||||||
|     return ExportSection { result.release_value() }; |     return ExportSection { result.release_value() }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ParseResult<StartSection::StartFunction> StartSection::StartFunction::parse(InputStream& stream) | ParseResult<StartSection::StartFunction> StartSection::StartFunction::parse(Core::Stream::Stream& stream) | ||||||
| { | { | ||||||
|     ScopeLogger<WASM_BINPARSER_DEBUG> logger("StartFunction"sv); |     ScopeLogger<WASM_BINPARSER_DEBUG> logger("StartFunction"sv); | ||||||
|     auto index = GenericIndexParser<FunctionIndex>::parse(stream); |     auto index = GenericIndexParser<FunctionIndex>::parse(stream); | ||||||
|  | @ -972,7 +991,7 @@ ParseResult<StartSection::StartFunction> StartSection::StartFunction::parse(Inpu | ||||||
|     return StartFunction { index.release_value() }; |     return StartFunction { index.release_value() }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ParseResult<StartSection> StartSection::parse(InputStream& stream) | ParseResult<StartSection> StartSection::parse(Core::Stream::Stream& stream) | ||||||
| { | { | ||||||
|     ScopeLogger<WASM_BINPARSER_DEBUG> logger("StartSection"sv); |     ScopeLogger<WASM_BINPARSER_DEBUG> logger("StartSection"sv); | ||||||
|     auto result = StartFunction::parse(stream); |     auto result = StartFunction::parse(stream); | ||||||
|  | @ -981,7 +1000,7 @@ ParseResult<StartSection> StartSection::parse(InputStream& stream) | ||||||
|     return StartSection { result.release_value() }; |     return StartSection { result.release_value() }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ParseResult<ElementSection::SegmentType0> ElementSection::SegmentType0::parse(InputStream& stream) | ParseResult<ElementSection::SegmentType0> ElementSection::SegmentType0::parse(Core::Stream::Stream& stream) | ||||||
| { | { | ||||||
|     auto expression = Expression::parse(stream); |     auto expression = Expression::parse(stream); | ||||||
|     if (expression.is_error()) |     if (expression.is_error()) | ||||||
|  | @ -993,12 +1012,13 @@ ParseResult<ElementSection::SegmentType0> ElementSection::SegmentType0::parse(In | ||||||
|     return SegmentType0 { indices.release_value(), Active { 0, expression.release_value() } }; |     return SegmentType0 { indices.release_value(), Active { 0, expression.release_value() } }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ParseResult<ElementSection::SegmentType1> ElementSection::SegmentType1::parse(InputStream& stream) | ParseResult<ElementSection::SegmentType1> ElementSection::SegmentType1::parse(Core::Stream::Stream& stream) | ||||||
| { | { | ||||||
|     u8 kind; |     auto kind_or_error = stream.read_value<u8>(); | ||||||
|     stream >> kind; |     if (kind_or_error.is_error()) | ||||||
|     if (stream.has_any_error()) |  | ||||||
|         return with_eof_check(stream, ParseError::ExpectedKindTag); |         return with_eof_check(stream, ParseError::ExpectedKindTag); | ||||||
|  | 
 | ||||||
|  |     auto kind = kind_or_error.release_value(); | ||||||
|     if (kind != 0) |     if (kind != 0) | ||||||
|         return ParseError::InvalidTag; |         return ParseError::InvalidTag; | ||||||
|     auto indices = parse_vector<GenericIndexParser<FunctionIndex>>(stream); |     auto indices = parse_vector<GenericIndexParser<FunctionIndex>>(stream); | ||||||
|  | @ -1008,56 +1028,57 @@ ParseResult<ElementSection::SegmentType1> ElementSection::SegmentType1::parse(In | ||||||
|     return SegmentType1 { indices.release_value() }; |     return SegmentType1 { indices.release_value() }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ParseResult<ElementSection::SegmentType2> ElementSection::SegmentType2::parse(InputStream& stream) | ParseResult<ElementSection::SegmentType2> ElementSection::SegmentType2::parse(Core::Stream::Stream& stream) | ||||||
| { | { | ||||||
|     dbgln("Type 2"); |     dbgln("Type 2"); | ||||||
|     (void)stream; |     (void)stream; | ||||||
|     return ParseError::NotImplemented; |     return ParseError::NotImplemented; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ParseResult<ElementSection::SegmentType3> ElementSection::SegmentType3::parse(InputStream& stream) | ParseResult<ElementSection::SegmentType3> ElementSection::SegmentType3::parse(Core::Stream::Stream& stream) | ||||||
| { | { | ||||||
|     dbgln("Type 3"); |     dbgln("Type 3"); | ||||||
|     (void)stream; |     (void)stream; | ||||||
|     return ParseError::NotImplemented; |     return ParseError::NotImplemented; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ParseResult<ElementSection::SegmentType4> ElementSection::SegmentType4::parse(InputStream& stream) | ParseResult<ElementSection::SegmentType4> ElementSection::SegmentType4::parse(Core::Stream::Stream& stream) | ||||||
| { | { | ||||||
|     dbgln("Type 4"); |     dbgln("Type 4"); | ||||||
|     (void)stream; |     (void)stream; | ||||||
|     return ParseError::NotImplemented; |     return ParseError::NotImplemented; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ParseResult<ElementSection::SegmentType5> ElementSection::SegmentType5::parse(InputStream& stream) | ParseResult<ElementSection::SegmentType5> ElementSection::SegmentType5::parse(Core::Stream::Stream& stream) | ||||||
| { | { | ||||||
|     dbgln("Type 5"); |     dbgln("Type 5"); | ||||||
|     (void)stream; |     (void)stream; | ||||||
|     return ParseError::NotImplemented; |     return ParseError::NotImplemented; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ParseResult<ElementSection::SegmentType6> ElementSection::SegmentType6::parse(InputStream& stream) | ParseResult<ElementSection::SegmentType6> ElementSection::SegmentType6::parse(Core::Stream::Stream& stream) | ||||||
| { | { | ||||||
|     dbgln("Type 6"); |     dbgln("Type 6"); | ||||||
|     (void)stream; |     (void)stream; | ||||||
|     return ParseError::NotImplemented; |     return ParseError::NotImplemented; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ParseResult<ElementSection::SegmentType7> ElementSection::SegmentType7::parse(InputStream& stream) | ParseResult<ElementSection::SegmentType7> ElementSection::SegmentType7::parse(Core::Stream::Stream& stream) | ||||||
| { | { | ||||||
|     dbgln("Type 7"); |     dbgln("Type 7"); | ||||||
|     (void)stream; |     (void)stream; | ||||||
|     return ParseError::NotImplemented; |     return ParseError::NotImplemented; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ParseResult<ElementSection::Element> ElementSection::Element::parse(InputStream& stream) | ParseResult<ElementSection::Element> ElementSection::Element::parse(Core::Stream::Stream& stream) | ||||||
| { | { | ||||||
|     ScopeLogger<WASM_BINPARSER_DEBUG> logger("Element"sv); |     ScopeLogger<WASM_BINPARSER_DEBUG> logger("Element"sv); | ||||||
|     u8 tag; |     auto tag_or_error = stream.read_value<u8>(); | ||||||
|     stream >> tag; |     if (tag_or_error.is_error()) | ||||||
|     if (stream.has_any_error()) |  | ||||||
|         return with_eof_check(stream, ParseError::ExpectedKindTag); |         return with_eof_check(stream, ParseError::ExpectedKindTag); | ||||||
| 
 | 
 | ||||||
|  |     auto tag = tag_or_error.release_value(); | ||||||
|  | 
 | ||||||
|     switch (tag) { |     switch (tag) { | ||||||
|     case 0x00: |     case 0x00: | ||||||
|         if (auto result = SegmentType0::parse(stream); result.is_error()) { |         if (auto result = SegmentType0::parse(stream); result.is_error()) { | ||||||
|  | @ -1118,7 +1139,7 @@ ParseResult<ElementSection::Element> ElementSection::Element::parse(InputStream& | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ParseResult<ElementSection> ElementSection::parse(InputStream& stream) | ParseResult<ElementSection> ElementSection::parse(Core::Stream::Stream& stream) | ||||||
| { | { | ||||||
|     ScopeLogger<WASM_BINPARSER_DEBUG> logger("ElementSection"sv); |     ScopeLogger<WASM_BINPARSER_DEBUG> logger("ElementSection"sv); | ||||||
|     auto result = parse_vector<Element>(stream); |     auto result = parse_vector<Element>(stream); | ||||||
|  | @ -1127,11 +1148,12 @@ ParseResult<ElementSection> ElementSection::parse(InputStream& stream) | ||||||
|     return ElementSection { result.release_value() }; |     return ElementSection { result.release_value() }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ParseResult<Locals> Locals::parse(InputStream& stream) | ParseResult<Locals> Locals::parse(Core::Stream::Stream& stream) | ||||||
| { | { | ||||||
|     ScopeLogger<WASM_BINPARSER_DEBUG> logger("Locals"sv); |     ScopeLogger<WASM_BINPARSER_DEBUG> logger("Locals"sv); | ||||||
|     size_t count; |     size_t count; | ||||||
|     if (!LEB128::read_unsigned(stream, count)) |     Core::Stream::WrapInAKInputStream wrapped_stream { stream }; | ||||||
|  |     if (!LEB128::read_unsigned(wrapped_stream, count)) | ||||||
|         return with_eof_check(stream, ParseError::InvalidSize); |         return with_eof_check(stream, ParseError::InvalidSize); | ||||||
| 
 | 
 | ||||||
|     if (count > Constants::max_allowed_function_locals_per_type) |     if (count > Constants::max_allowed_function_locals_per_type) | ||||||
|  | @ -1144,7 +1166,7 @@ ParseResult<Locals> Locals::parse(InputStream& stream) | ||||||
|     return Locals { static_cast<u32>(count), type.release_value() }; |     return Locals { static_cast<u32>(count), type.release_value() }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ParseResult<CodeSection::Func> CodeSection::Func::parse(InputStream& stream) | ParseResult<CodeSection::Func> CodeSection::Func::parse(Core::Stream::Stream& stream) | ||||||
| { | { | ||||||
|     ScopeLogger<WASM_BINPARSER_DEBUG> logger("Func"sv); |     ScopeLogger<WASM_BINPARSER_DEBUG> logger("Func"sv); | ||||||
|     auto locals = parse_vector<Locals>(stream); |     auto locals = parse_vector<Locals>(stream); | ||||||
|  | @ -1156,19 +1178,15 @@ ParseResult<CodeSection::Func> CodeSection::Func::parse(InputStream& stream) | ||||||
|     return Func { locals.release_value(), body.release_value() }; |     return Func { locals.release_value(), body.release_value() }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ParseResult<CodeSection::Code> CodeSection::Code::parse(InputStream& stream) | ParseResult<CodeSection::Code> CodeSection::Code::parse(Core::Stream::Stream& stream) | ||||||
| { | { | ||||||
|     ScopeLogger<WASM_BINPARSER_DEBUG> logger("Code"sv); |     ScopeLogger<WASM_BINPARSER_DEBUG> logger("Code"sv); | ||||||
|     size_t size; |     size_t size; | ||||||
|     if (!LEB128::read_unsigned(stream, size)) |     Core::Stream::WrapInAKInputStream wrapped_stream { stream }; | ||||||
|  |     if (!LEB128::read_unsigned(wrapped_stream, size)) | ||||||
|         return with_eof_check(stream, ParseError::InvalidSize); |         return with_eof_check(stream, ParseError::InvalidSize); | ||||||
| 
 | 
 | ||||||
|     auto constrained_stream = ConstrainedStream { stream, size }; |     auto constrained_stream = ConstrainedStream { stream, size }; | ||||||
|     ScopeGuard drain_errors { |  | ||||||
|         [&] { |  | ||||||
|             constrained_stream.handle_any_error(); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| 
 | 
 | ||||||
|     auto func = Func::parse(constrained_stream); |     auto func = Func::parse(constrained_stream); | ||||||
|     if (func.is_error()) |     if (func.is_error()) | ||||||
|  | @ -1177,7 +1195,7 @@ ParseResult<CodeSection::Code> CodeSection::Code::parse(InputStream& stream) | ||||||
|     return Code { static_cast<u32>(size), func.release_value() }; |     return Code { static_cast<u32>(size), func.release_value() }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ParseResult<CodeSection> CodeSection::parse(InputStream& stream) | ParseResult<CodeSection> CodeSection::parse(Core::Stream::Stream& stream) | ||||||
| { | { | ||||||
|     ScopeLogger<WASM_BINPARSER_DEBUG> logger("CodeSection"sv); |     ScopeLogger<WASM_BINPARSER_DEBUG> logger("CodeSection"sv); | ||||||
|     auto result = parse_vector<Code>(stream); |     auto result = parse_vector<Code>(stream); | ||||||
|  | @ -1186,14 +1204,15 @@ ParseResult<CodeSection> CodeSection::parse(InputStream& stream) | ||||||
|     return CodeSection { result.release_value() }; |     return CodeSection { result.release_value() }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ParseResult<DataSection::Data> DataSection::Data::parse(InputStream& stream) | ParseResult<DataSection::Data> DataSection::Data::parse(Core::Stream::Stream& stream) | ||||||
| { | { | ||||||
|     ScopeLogger<WASM_BINPARSER_DEBUG> logger("Data"sv); |     ScopeLogger<WASM_BINPARSER_DEBUG> logger("Data"sv); | ||||||
|     u8 tag; |     auto tag_or_error = stream.read_value<u8>(); | ||||||
|     stream >> tag; |     if (tag_or_error.is_error()) | ||||||
|     if (stream.has_any_error()) |  | ||||||
|         return with_eof_check(stream, ParseError::ExpectedKindTag); |         return with_eof_check(stream, ParseError::ExpectedKindTag); | ||||||
| 
 | 
 | ||||||
|  |     auto tag = tag_or_error.release_value(); | ||||||
|  | 
 | ||||||
|     if (tag > 0x02) |     if (tag > 0x02) | ||||||
|         return with_eof_check(stream, ParseError::InvalidTag); |         return with_eof_check(stream, ParseError::InvalidTag); | ||||||
| 
 | 
 | ||||||
|  | @ -1227,7 +1246,7 @@ ParseResult<DataSection::Data> DataSection::Data::parse(InputStream& stream) | ||||||
|     VERIFY_NOT_REACHED(); |     VERIFY_NOT_REACHED(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ParseResult<DataSection> DataSection::parse(InputStream& stream) | ParseResult<DataSection> DataSection::parse(Core::Stream::Stream& stream) | ||||||
| { | { | ||||||
|     ScopeLogger<WASM_BINPARSER_DEBUG> logger("DataSection"sv); |     ScopeLogger<WASM_BINPARSER_DEBUG> logger("DataSection"sv); | ||||||
|     auto data = parse_vector<Data>(stream); |     auto data = parse_vector<Data>(stream); | ||||||
|  | @ -1237,12 +1256,13 @@ ParseResult<DataSection> DataSection::parse(InputStream& stream) | ||||||
|     return DataSection { data.release_value() }; |     return DataSection { data.release_value() }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ParseResult<DataCountSection> DataCountSection::parse([[maybe_unused]] InputStream& stream) | ParseResult<DataCountSection> DataCountSection::parse([[maybe_unused]] Core::Stream::Stream& stream) | ||||||
| { | { | ||||||
|     ScopeLogger<WASM_BINPARSER_DEBUG> logger("DataCountSection"sv); |     ScopeLogger<WASM_BINPARSER_DEBUG> logger("DataCountSection"sv); | ||||||
|     u32 value; |     u32 value; | ||||||
|     if (!LEB128::read_unsigned(stream, value)) { |     Core::Stream::WrapInAKInputStream wrapped_stream { stream }; | ||||||
|         if (stream.unreliable_eof()) { |     if (!LEB128::read_unsigned(wrapped_stream, value)) { | ||||||
|  |         if (stream.is_eof()) { | ||||||
|             // The section simply didn't contain anything.
 |             // The section simply didn't contain anything.
 | ||||||
|             return DataCountSection { {} }; |             return DataCountSection { {} }; | ||||||
|         } |         } | ||||||
|  | @ -1252,41 +1272,36 @@ ParseResult<DataCountSection> DataCountSection::parse([[maybe_unused]] InputStre | ||||||
|     return DataCountSection { value }; |     return DataCountSection { value }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ParseResult<Module> Module::parse(InputStream& stream) | ParseResult<Module> Module::parse(Core::Stream::Stream& stream) | ||||||
| { | { | ||||||
|     ScopeLogger<WASM_BINPARSER_DEBUG> logger("Module"sv); |     ScopeLogger<WASM_BINPARSER_DEBUG> logger("Module"sv); | ||||||
|     u8 buf[4]; |     u8 buf[4]; | ||||||
|     if (!stream.read_or_error({ buf, 4 })) |     if (stream.read_entire_buffer({ buf, 4 }).is_error()) | ||||||
|         return with_eof_check(stream, ParseError::InvalidInput); |         return with_eof_check(stream, ParseError::InvalidInput); | ||||||
|     if (Bytes { buf, 4 } != wasm_magic.span()) |     if (Bytes { buf, 4 } != wasm_magic.span()) | ||||||
|         return with_eof_check(stream, ParseError::InvalidModuleMagic); |         return with_eof_check(stream, ParseError::InvalidModuleMagic); | ||||||
| 
 | 
 | ||||||
|     if (!stream.read_or_error({ buf, 4 })) |     if (stream.read_entire_buffer({ buf, 4 }).is_error()) | ||||||
|         return with_eof_check(stream, ParseError::InvalidInput); |         return with_eof_check(stream, ParseError::InvalidInput); | ||||||
|     if (Bytes { buf, 4 } != wasm_version.span()) |     if (Bytes { buf, 4 } != wasm_version.span()) | ||||||
|         return with_eof_check(stream, ParseError::InvalidModuleVersion); |         return with_eof_check(stream, ParseError::InvalidModuleVersion); | ||||||
| 
 | 
 | ||||||
|     Vector<AnySection> sections; |     Vector<AnySection> sections; | ||||||
|     for (;;) { |     for (;;) { | ||||||
|         u8 section_id; |         auto section_id_or_error = stream.read_value<u8>(); | ||||||
|         stream >> section_id; |         if (stream.is_eof()) | ||||||
|         if (stream.unreliable_eof()) { |  | ||||||
|             stream.handle_any_error(); |  | ||||||
|             break; |             break; | ||||||
|         } |         if (section_id_or_error.is_error()) | ||||||
|         if (stream.has_any_error()) |  | ||||||
|             return with_eof_check(stream, ParseError::ExpectedIndex); |             return with_eof_check(stream, ParseError::ExpectedIndex); | ||||||
| 
 | 
 | ||||||
|  |         auto section_id = section_id_or_error.release_value(); | ||||||
|  | 
 | ||||||
|         size_t section_size; |         size_t section_size; | ||||||
|         if (!LEB128::read_unsigned(stream, section_size)) |         Core::Stream::WrapInAKInputStream wrapped_stream { stream }; | ||||||
|  |         if (!LEB128::read_unsigned(wrapped_stream, section_size)) | ||||||
|             return with_eof_check(stream, ParseError::ExpectedSize); |             return with_eof_check(stream, ParseError::ExpectedSize); | ||||||
| 
 | 
 | ||||||
|         auto section_stream = ConstrainedStream { stream, section_size }; |         auto section_stream = ConstrainedStream { stream, section_size }; | ||||||
|         ScopeGuard drain_errors { |  | ||||||
|             [&] { |  | ||||||
|                 section_stream.handle_any_error(); |  | ||||||
|             } |  | ||||||
|         }; |  | ||||||
| 
 | 
 | ||||||
|         switch (section_id) { |         switch (section_id) { | ||||||
|         case CustomSection::section_id: |         case CustomSection::section_id: | ||||||
|  |  | ||||||
|  | @ -13,6 +13,7 @@ | ||||||
| #include <AK/NonnullOwnPtrVector.h> | #include <AK/NonnullOwnPtrVector.h> | ||||||
| #include <AK/Result.h> | #include <AK/Result.h> | ||||||
| #include <AK/Variant.h> | #include <AK/Variant.h> | ||||||
|  | #include <LibCore/Stream.h> | ||||||
| #include <LibWasm/Constants.h> | #include <LibWasm/Constants.h> | ||||||
| #include <LibWasm/Forward.h> | #include <LibWasm/Forward.h> | ||||||
| #include <LibWasm/Opcode.h> | #include <LibWasm/Opcode.h> | ||||||
|  | @ -58,22 +59,23 @@ AK_TYPEDEF_DISTINCT_ORDERED_ID(size_t, LabelIndex); | ||||||
| AK_TYPEDEF_DISTINCT_ORDERED_ID(size_t, DataIndex); | AK_TYPEDEF_DISTINCT_ORDERED_ID(size_t, DataIndex); | ||||||
| AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, InstructionPointer, Arithmetic, Comparison, Flags, Increment); | AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, InstructionPointer, Arithmetic, Comparison, Flags, Increment); | ||||||
| 
 | 
 | ||||||
| ParseError with_eof_check(InputStream const& stream, ParseError error_if_not_eof); | ParseError with_eof_check(Core::Stream::Stream const& stream, ParseError error_if_not_eof); | ||||||
| 
 | 
 | ||||||
| template<typename T> | template<typename T> | ||||||
| struct GenericIndexParser { | struct GenericIndexParser { | ||||||
|     static ParseResult<T> parse(InputStream& stream) |     static ParseResult<T> parse(Core::Stream::Stream& stream) | ||||||
|     { |     { | ||||||
|         size_t value; |         size_t value; | ||||||
|         if (!LEB128::read_unsigned(stream, value)) |         Core::Stream::WrapInAKInputStream wrapped_stream { stream }; | ||||||
|  |         if (!LEB128::read_unsigned(wrapped_stream, value)) | ||||||
|             return with_eof_check(stream, ParseError::ExpectedIndex); |             return with_eof_check(stream, ParseError::ExpectedIndex); | ||||||
|         return T { value }; |         return T { value }; | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| class ReconsumableStream : public InputStream { | class ReconsumableStream : public Core::Stream::Stream { | ||||||
| public: | public: | ||||||
|     explicit ReconsumableStream(InputStream& stream) |     explicit ReconsumableStream(Core::Stream::Stream& stream) | ||||||
|         : m_stream(stream) |         : m_stream(stream) | ||||||
|     { |     { | ||||||
|     } |     } | ||||||
|  | @ -81,8 +83,10 @@ public: | ||||||
|     void unread(ReadonlyBytes data) { m_buffer.append(data.data(), data.size()); } |     void unread(ReadonlyBytes data) { m_buffer.append(data.data(), data.size()); } | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     size_t read(Bytes bytes) override |     virtual ErrorOr<Bytes> read(Bytes bytes) override | ||||||
|     { |     { | ||||||
|  |         auto original_bytes = bytes; | ||||||
|  | 
 | ||||||
|         size_t bytes_read_from_buffer = 0; |         size_t bytes_read_from_buffer = 0; | ||||||
|         if (!m_buffer.is_empty()) { |         if (!m_buffer.is_empty()) { | ||||||
|             auto read_size = min(bytes.size(), m_buffer.size()); |             auto read_size = min(bytes.size(), m_buffer.size()); | ||||||
|  | @ -93,20 +97,15 @@ private: | ||||||
|             bytes_read_from_buffer = read_size; |             bytes_read_from_buffer = read_size; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return m_stream.read(bytes) + bytes_read_from_buffer; |         return original_bytes.trim(TRY(m_stream.read(bytes)).size() + bytes_read_from_buffer); | ||||||
|     } |     } | ||||||
|     bool unreliable_eof() const override | 
 | ||||||
|  |     virtual bool is_eof() const override | ||||||
|     { |     { | ||||||
|         return m_buffer.is_empty() && m_stream.unreliable_eof(); |         return m_buffer.is_empty() && m_stream.is_eof(); | ||||||
|     } |     } | ||||||
|     bool read_or_error(Bytes bytes) override | 
 | ||||||
|     { |     virtual ErrorOr<void> discard(size_t count) override | ||||||
|         if (read(bytes)) |  | ||||||
|             return true; |  | ||||||
|         set_recoverable_error(); |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
|     bool discard_or_error(size_t count) override |  | ||||||
|     { |     { | ||||||
|         size_t bytes_discarded_from_buffer = 0; |         size_t bytes_discarded_from_buffer = 0; | ||||||
|         if (!m_buffer.is_empty()) { |         if (!m_buffer.is_empty()) { | ||||||
|  | @ -116,49 +115,74 @@ private: | ||||||
|             bytes_discarded_from_buffer = read_size; |             bytes_discarded_from_buffer = read_size; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return m_stream.discard_or_error(count - bytes_discarded_from_buffer); |         return m_stream.discard(count - bytes_discarded_from_buffer); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     InputStream& m_stream; |     virtual ErrorOr<size_t> write(ReadonlyBytes) override | ||||||
|  |     { | ||||||
|  |         return Error::from_errno(EBADF); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     virtual bool is_open() const override | ||||||
|  |     { | ||||||
|  |         return m_stream.is_open(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     virtual void close() override | ||||||
|  |     { | ||||||
|  |         m_stream.close(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     Core::Stream::Stream& m_stream; | ||||||
|     Vector<u8, 8> m_buffer; |     Vector<u8, 8> m_buffer; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| class ConstrainedStream : public InputStream { | class ConstrainedStream : public Core::Stream::Stream { | ||||||
| public: | public: | ||||||
|     explicit ConstrainedStream(InputStream& stream, size_t size) |     explicit ConstrainedStream(Core::Stream::Stream& stream, size_t size) | ||||||
|         : m_stream(stream) |         : m_stream(stream) | ||||||
|         , m_bytes_left(size) |         , m_bytes_left(size) | ||||||
|     { |     { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     size_t read(Bytes bytes) override |     ErrorOr<Bytes> read(Bytes bytes) override | ||||||
|     { |     { | ||||||
|         auto to_read = min(m_bytes_left, bytes.size()); |         auto to_read = min(m_bytes_left, bytes.size()); | ||||||
|         auto nread = m_stream.read(bytes.slice(0, to_read)); |         auto read_bytes = TRY(m_stream.read(bytes.slice(0, to_read))); | ||||||
|         m_bytes_left -= nread; |         m_bytes_left -= read_bytes.size(); | ||||||
|         return nread; |         return read_bytes; | ||||||
|     } |  | ||||||
|     bool unreliable_eof() const override |  | ||||||
|     { |  | ||||||
|         return m_bytes_left == 0 || m_stream.unreliable_eof(); |  | ||||||
|     } |  | ||||||
|     bool read_or_error(Bytes bytes) override |  | ||||||
|     { |  | ||||||
|         if (read(bytes)) |  | ||||||
|             return true; |  | ||||||
|         set_recoverable_error(); |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
|     bool discard_or_error(size_t count) override |  | ||||||
|     { |  | ||||||
|         auto to_discard = min(m_bytes_left, count); |  | ||||||
|         if (m_stream.discard_or_error(to_discard)) |  | ||||||
|             m_bytes_left -= to_discard; |  | ||||||
|         return to_discard; |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     InputStream& m_stream; |     bool is_eof() const override | ||||||
|  |     { | ||||||
|  |         return m_bytes_left == 0 || m_stream.is_eof(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     ErrorOr<void> discard(size_t count) override | ||||||
|  |     { | ||||||
|  |         if (count > m_bytes_left) | ||||||
|  |             return Error::from_string_literal("Trying to discard more bytes than allowed"); | ||||||
|  | 
 | ||||||
|  |         return m_stream.discard(count); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     virtual ErrorOr<size_t> write(ReadonlyBytes) override | ||||||
|  |     { | ||||||
|  |         return Error::from_errno(EBADF); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     virtual bool is_open() const override | ||||||
|  |     { | ||||||
|  |         return m_stream.is_open(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     virtual void close() override | ||||||
|  |     { | ||||||
|  |         m_stream.close(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     Core::Stream::Stream& m_stream; | ||||||
|     size_t m_bytes_left { 0 }; |     size_t m_bytes_left { 0 }; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -187,7 +211,7 @@ public: | ||||||
|     auto is_numeric() const { return !is_reference(); } |     auto is_numeric() const { return !is_reference(); } | ||||||
|     auto kind() const { return m_kind; } |     auto kind() const { return m_kind; } | ||||||
| 
 | 
 | ||||||
|     static ParseResult<ValueType> parse(InputStream& stream); |     static ParseResult<ValueType> parse(Core::Stream::Stream& stream); | ||||||
| 
 | 
 | ||||||
|     static DeprecatedString kind_name(Kind kind) |     static DeprecatedString kind_name(Kind kind) | ||||||
|     { |     { | ||||||
|  | @ -226,7 +250,7 @@ public: | ||||||
| 
 | 
 | ||||||
|     auto const& types() const { return m_types; } |     auto const& types() const { return m_types; } | ||||||
| 
 | 
 | ||||||
|     static ParseResult<ResultType> parse(InputStream& stream); |     static ParseResult<ResultType> parse(Core::Stream::Stream& stream); | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     Vector<ValueType> m_types; |     Vector<ValueType> m_types; | ||||||
|  | @ -244,7 +268,7 @@ public: | ||||||
|     auto& parameters() const { return m_parameters; } |     auto& parameters() const { return m_parameters; } | ||||||
|     auto& results() const { return m_results; } |     auto& results() const { return m_results; } | ||||||
| 
 | 
 | ||||||
|     static ParseResult<FunctionType> parse(InputStream& stream); |     static ParseResult<FunctionType> parse(Core::Stream::Stream& stream); | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     Vector<ValueType> m_parameters; |     Vector<ValueType> m_parameters; | ||||||
|  | @ -263,7 +287,7 @@ public: | ||||||
|     auto min() const { return m_min; } |     auto min() const { return m_min; } | ||||||
|     auto& max() const { return m_max; } |     auto& max() const { return m_max; } | ||||||
| 
 | 
 | ||||||
|     static ParseResult<Limits> parse(InputStream& stream); |     static ParseResult<Limits> parse(Core::Stream::Stream& stream); | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     u32 m_min { 0 }; |     u32 m_min { 0 }; | ||||||
|  | @ -280,7 +304,7 @@ public: | ||||||
| 
 | 
 | ||||||
|     auto& limits() const { return m_limits; } |     auto& limits() const { return m_limits; } | ||||||
| 
 | 
 | ||||||
|     static ParseResult<MemoryType> parse(InputStream& stream); |     static ParseResult<MemoryType> parse(Core::Stream::Stream& stream); | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     Limits m_limits; |     Limits m_limits; | ||||||
|  | @ -299,7 +323,7 @@ public: | ||||||
|     auto& limits() const { return m_limits; } |     auto& limits() const { return m_limits; } | ||||||
|     auto& element_type() const { return m_element_type; } |     auto& element_type() const { return m_element_type; } | ||||||
| 
 | 
 | ||||||
|     static ParseResult<TableType> parse(InputStream& stream); |     static ParseResult<TableType> parse(Core::Stream::Stream& stream); | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     ValueType m_element_type; |     ValueType m_element_type; | ||||||
|  | @ -318,7 +342,7 @@ public: | ||||||
|     auto& type() const { return m_type; } |     auto& type() const { return m_type; } | ||||||
|     auto is_mutable() const { return m_is_mutable; } |     auto is_mutable() const { return m_is_mutable; } | ||||||
| 
 | 
 | ||||||
|     static ParseResult<GlobalType> parse(InputStream& stream); |     static ParseResult<GlobalType> parse(Core::Stream::Stream& stream); | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     ValueType m_type; |     ValueType m_type; | ||||||
|  | @ -364,7 +388,7 @@ public: | ||||||
|         return m_type_index; |         return m_type_index; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     static ParseResult<BlockType> parse(InputStream& stream); |     static ParseResult<BlockType> parse(Core::Stream::Stream& stream); | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     Kind m_kind { Empty }; |     Kind m_kind { Empty }; | ||||||
|  | @ -428,7 +452,7 @@ public: | ||||||
|     { |     { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     static ParseResult<Vector<Instruction>> parse(InputStream& stream, InstructionPointer& ip); |     static ParseResult<Vector<Instruction>> parse(Core::Stream::Stream& stream, InstructionPointer& ip); | ||||||
| 
 | 
 | ||||||
|     auto& opcode() const { return m_opcode; } |     auto& opcode() const { return m_opcode; } | ||||||
|     auto& arguments() const { return m_arguments; } |     auto& arguments() const { return m_arguments; } | ||||||
|  | @ -475,7 +499,7 @@ public: | ||||||
|     auto& name() const { return m_name; } |     auto& name() const { return m_name; } | ||||||
|     auto& contents() const { return m_contents; } |     auto& contents() const { return m_contents; } | ||||||
| 
 | 
 | ||||||
|     static ParseResult<CustomSection> parse(InputStream& stream); |     static ParseResult<CustomSection> parse(Core::Stream::Stream& stream); | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     DeprecatedString m_name; |     DeprecatedString m_name; | ||||||
|  | @ -493,7 +517,7 @@ public: | ||||||
| 
 | 
 | ||||||
|     auto& types() const { return m_types; } |     auto& types() const { return m_types; } | ||||||
| 
 | 
 | ||||||
|     static ParseResult<TypeSection> parse(InputStream& stream); |     static ParseResult<TypeSection> parse(Core::Stream::Stream& stream); | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     Vector<FunctionType> m_types; |     Vector<FunctionType> m_types; | ||||||
|  | @ -515,7 +539,7 @@ public: | ||||||
|         auto& name() const { return m_name; } |         auto& name() const { return m_name; } | ||||||
|         auto& description() const { return m_description; } |         auto& description() const { return m_description; } | ||||||
| 
 | 
 | ||||||
|         static ParseResult<Import> parse(InputStream& stream); |         static ParseResult<Import> parse(Core::Stream::Stream& stream); | ||||||
| 
 | 
 | ||||||
|     private: |     private: | ||||||
|         template<typename T> |         template<typename T> | ||||||
|  | @ -542,7 +566,7 @@ public: | ||||||
| 
 | 
 | ||||||
|     auto& imports() const { return m_imports; } |     auto& imports() const { return m_imports; } | ||||||
| 
 | 
 | ||||||
|     static ParseResult<ImportSection> parse(InputStream& stream); |     static ParseResult<ImportSection> parse(Core::Stream::Stream& stream); | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     Vector<Import> m_imports; |     Vector<Import> m_imports; | ||||||
|  | @ -559,7 +583,7 @@ public: | ||||||
| 
 | 
 | ||||||
|     auto& types() const { return m_types; } |     auto& types() const { return m_types; } | ||||||
| 
 | 
 | ||||||
|     static ParseResult<FunctionSection> parse(InputStream& stream); |     static ParseResult<FunctionSection> parse(Core::Stream::Stream& stream); | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     Vector<TypeIndex> m_types; |     Vector<TypeIndex> m_types; | ||||||
|  | @ -576,7 +600,7 @@ public: | ||||||
| 
 | 
 | ||||||
|         auto& type() const { return m_type; } |         auto& type() const { return m_type; } | ||||||
| 
 | 
 | ||||||
|         static ParseResult<Table> parse(InputStream& stream); |         static ParseResult<Table> parse(Core::Stream::Stream& stream); | ||||||
| 
 | 
 | ||||||
|     private: |     private: | ||||||
|         TableType m_type; |         TableType m_type; | ||||||
|  | @ -592,7 +616,7 @@ public: | ||||||
| 
 | 
 | ||||||
|     auto& tables() const { return m_tables; }; |     auto& tables() const { return m_tables; }; | ||||||
| 
 | 
 | ||||||
|     static ParseResult<TableSection> parse(InputStream& stream); |     static ParseResult<TableSection> parse(Core::Stream::Stream& stream); | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     Vector<Table> m_tables; |     Vector<Table> m_tables; | ||||||
|  | @ -609,7 +633,7 @@ public: | ||||||
| 
 | 
 | ||||||
|         auto& type() const { return m_type; } |         auto& type() const { return m_type; } | ||||||
| 
 | 
 | ||||||
|         static ParseResult<Memory> parse(InputStream& stream); |         static ParseResult<Memory> parse(Core::Stream::Stream& stream); | ||||||
| 
 | 
 | ||||||
|     private: |     private: | ||||||
|         MemoryType m_type; |         MemoryType m_type; | ||||||
|  | @ -625,7 +649,7 @@ public: | ||||||
| 
 | 
 | ||||||
|     auto& memories() const { return m_memories; } |     auto& memories() const { return m_memories; } | ||||||
| 
 | 
 | ||||||
|     static ParseResult<MemorySection> parse(InputStream& stream); |     static ParseResult<MemorySection> parse(Core::Stream::Stream& stream); | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     Vector<Memory> m_memories; |     Vector<Memory> m_memories; | ||||||
|  | @ -640,7 +664,7 @@ public: | ||||||
| 
 | 
 | ||||||
|     auto& instructions() const { return m_instructions; } |     auto& instructions() const { return m_instructions; } | ||||||
| 
 | 
 | ||||||
|     static ParseResult<Expression> parse(InputStream& stream); |     static ParseResult<Expression> parse(Core::Stream::Stream& stream); | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     Vector<Instruction> m_instructions; |     Vector<Instruction> m_instructions; | ||||||
|  | @ -659,7 +683,7 @@ public: | ||||||
|         auto& type() const { return m_type; } |         auto& type() const { return m_type; } | ||||||
|         auto& expression() const { return m_expression; } |         auto& expression() const { return m_expression; } | ||||||
| 
 | 
 | ||||||
|         static ParseResult<Global> parse(InputStream& stream); |         static ParseResult<Global> parse(Core::Stream::Stream& stream); | ||||||
| 
 | 
 | ||||||
|     private: |     private: | ||||||
|         GlobalType m_type; |         GlobalType m_type; | ||||||
|  | @ -676,7 +700,7 @@ public: | ||||||
| 
 | 
 | ||||||
|     auto& entries() const { return m_entries; } |     auto& entries() const { return m_entries; } | ||||||
| 
 | 
 | ||||||
|     static ParseResult<GlobalSection> parse(InputStream& stream); |     static ParseResult<GlobalSection> parse(Core::Stream::Stream& stream); | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     Vector<Global> m_entries; |     Vector<Global> m_entries; | ||||||
|  | @ -698,7 +722,7 @@ public: | ||||||
|         auto& name() const { return m_name; } |         auto& name() const { return m_name; } | ||||||
|         auto& description() const { return m_description; } |         auto& description() const { return m_description; } | ||||||
| 
 | 
 | ||||||
|         static ParseResult<Export> parse(InputStream& stream); |         static ParseResult<Export> parse(Core::Stream::Stream& stream); | ||||||
| 
 | 
 | ||||||
|     private: |     private: | ||||||
|         DeprecatedString m_name; |         DeprecatedString m_name; | ||||||
|  | @ -714,7 +738,7 @@ public: | ||||||
| 
 | 
 | ||||||
|     auto& entries() const { return m_entries; } |     auto& entries() const { return m_entries; } | ||||||
| 
 | 
 | ||||||
|     static ParseResult<ExportSection> parse(InputStream& stream); |     static ParseResult<ExportSection> parse(Core::Stream::Stream& stream); | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     Vector<Export> m_entries; |     Vector<Export> m_entries; | ||||||
|  | @ -731,7 +755,7 @@ public: | ||||||
| 
 | 
 | ||||||
|         auto& index() const { return m_index; } |         auto& index() const { return m_index; } | ||||||
| 
 | 
 | ||||||
|         static ParseResult<StartFunction> parse(InputStream& stream); |         static ParseResult<StartFunction> parse(Core::Stream::Stream& stream); | ||||||
| 
 | 
 | ||||||
|     private: |     private: | ||||||
|         FunctionIndex m_index; |         FunctionIndex m_index; | ||||||
|  | @ -746,7 +770,7 @@ public: | ||||||
| 
 | 
 | ||||||
|     auto& function() const { return m_function; } |     auto& function() const { return m_function; } | ||||||
| 
 | 
 | ||||||
|     static ParseResult<StartSection> parse(InputStream& stream); |     static ParseResult<StartSection> parse(Core::Stream::Stream& stream); | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     StartFunction m_function; |     StartFunction m_function; | ||||||
|  | @ -765,43 +789,43 @@ public: | ||||||
| 
 | 
 | ||||||
|     struct SegmentType0 { |     struct SegmentType0 { | ||||||
|         // FIXME: Implement me!
 |         // FIXME: Implement me!
 | ||||||
|         static ParseResult<SegmentType0> parse(InputStream& stream); |         static ParseResult<SegmentType0> parse(Core::Stream::Stream& stream); | ||||||
| 
 | 
 | ||||||
|         Vector<FunctionIndex> function_indices; |         Vector<FunctionIndex> function_indices; | ||||||
|         Active mode; |         Active mode; | ||||||
|     }; |     }; | ||||||
|     struct SegmentType1 { |     struct SegmentType1 { | ||||||
|         static ParseResult<SegmentType1> parse(InputStream& stream); |         static ParseResult<SegmentType1> parse(Core::Stream::Stream& stream); | ||||||
| 
 | 
 | ||||||
|         Vector<FunctionIndex> function_indices; |         Vector<FunctionIndex> function_indices; | ||||||
|     }; |     }; | ||||||
|     struct SegmentType2 { |     struct SegmentType2 { | ||||||
|         // FIXME: Implement me!
 |         // FIXME: Implement me!
 | ||||||
|         static ParseResult<SegmentType2> parse(InputStream& stream); |         static ParseResult<SegmentType2> parse(Core::Stream::Stream& stream); | ||||||
|     }; |     }; | ||||||
|     struct SegmentType3 { |     struct SegmentType3 { | ||||||
|         // FIXME: Implement me!
 |         // FIXME: Implement me!
 | ||||||
|         static ParseResult<SegmentType3> parse(InputStream& stream); |         static ParseResult<SegmentType3> parse(Core::Stream::Stream& stream); | ||||||
|     }; |     }; | ||||||
|     struct SegmentType4 { |     struct SegmentType4 { | ||||||
|         // FIXME: Implement me!
 |         // FIXME: Implement me!
 | ||||||
|         static ParseResult<SegmentType4> parse(InputStream& stream); |         static ParseResult<SegmentType4> parse(Core::Stream::Stream& stream); | ||||||
|     }; |     }; | ||||||
|     struct SegmentType5 { |     struct SegmentType5 { | ||||||
|         // FIXME: Implement me!
 |         // FIXME: Implement me!
 | ||||||
|         static ParseResult<SegmentType5> parse(InputStream& stream); |         static ParseResult<SegmentType5> parse(Core::Stream::Stream& stream); | ||||||
|     }; |     }; | ||||||
|     struct SegmentType6 { |     struct SegmentType6 { | ||||||
|         // FIXME: Implement me!
 |         // FIXME: Implement me!
 | ||||||
|         static ParseResult<SegmentType6> parse(InputStream& stream); |         static ParseResult<SegmentType6> parse(Core::Stream::Stream& stream); | ||||||
|     }; |     }; | ||||||
|     struct SegmentType7 { |     struct SegmentType7 { | ||||||
|         // FIXME: Implement me!
 |         // FIXME: Implement me!
 | ||||||
|         static ParseResult<SegmentType7> parse(InputStream& stream); |         static ParseResult<SegmentType7> parse(Core::Stream::Stream& stream); | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     struct Element { |     struct Element { | ||||||
|         static ParseResult<Element> parse(InputStream&); |         static ParseResult<Element> parse(Core::Stream::Stream&); | ||||||
| 
 | 
 | ||||||
|         ValueType type; |         ValueType type; | ||||||
|         Vector<Expression> init; |         Vector<Expression> init; | ||||||
|  | @ -817,7 +841,7 @@ public: | ||||||
| 
 | 
 | ||||||
|     auto& segments() const { return m_segments; } |     auto& segments() const { return m_segments; } | ||||||
| 
 | 
 | ||||||
|     static ParseResult<ElementSection> parse(InputStream& stream); |     static ParseResult<ElementSection> parse(Core::Stream::Stream& stream); | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     Vector<Element> m_segments; |     Vector<Element> m_segments; | ||||||
|  | @ -835,7 +859,7 @@ public: | ||||||
|     auto n() const { return m_n; } |     auto n() const { return m_n; } | ||||||
|     auto& type() const { return m_type; } |     auto& type() const { return m_type; } | ||||||
| 
 | 
 | ||||||
|     static ParseResult<Locals> parse(InputStream& stream); |     static ParseResult<Locals> parse(Core::Stream::Stream& stream); | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     u32 m_n { 0 }; |     u32 m_n { 0 }; | ||||||
|  | @ -856,7 +880,7 @@ public: | ||||||
|         auto& locals() const { return m_locals; } |         auto& locals() const { return m_locals; } | ||||||
|         auto& body() const { return m_body; } |         auto& body() const { return m_body; } | ||||||
| 
 | 
 | ||||||
|         static ParseResult<Func> parse(InputStream& stream); |         static ParseResult<Func> parse(Core::Stream::Stream& stream); | ||||||
| 
 | 
 | ||||||
|     private: |     private: | ||||||
|         Vector<Locals> m_locals; |         Vector<Locals> m_locals; | ||||||
|  | @ -873,7 +897,7 @@ public: | ||||||
|         auto size() const { return m_size; } |         auto size() const { return m_size; } | ||||||
|         auto& func() const { return m_func; } |         auto& func() const { return m_func; } | ||||||
| 
 | 
 | ||||||
|         static ParseResult<Code> parse(InputStream& stream); |         static ParseResult<Code> parse(Core::Stream::Stream& stream); | ||||||
| 
 | 
 | ||||||
|     private: |     private: | ||||||
|         u32 m_size { 0 }; |         u32 m_size { 0 }; | ||||||
|  | @ -889,7 +913,7 @@ public: | ||||||
| 
 | 
 | ||||||
|     auto& functions() const { return m_functions; } |     auto& functions() const { return m_functions; } | ||||||
| 
 | 
 | ||||||
|     static ParseResult<CodeSection> parse(InputStream& stream); |     static ParseResult<CodeSection> parse(Core::Stream::Stream& stream); | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     Vector<Code> m_functions; |     Vector<Code> m_functions; | ||||||
|  | @ -916,7 +940,7 @@ public: | ||||||
| 
 | 
 | ||||||
|         auto& value() const { return m_value; } |         auto& value() const { return m_value; } | ||||||
| 
 | 
 | ||||||
|         static ParseResult<Data> parse(InputStream& stream); |         static ParseResult<Data> parse(Core::Stream::Stream& stream); | ||||||
| 
 | 
 | ||||||
|     private: |     private: | ||||||
|         Value m_value; |         Value m_value; | ||||||
|  | @ -931,7 +955,7 @@ public: | ||||||
| 
 | 
 | ||||||
|     auto& data() const { return m_data; } |     auto& data() const { return m_data; } | ||||||
| 
 | 
 | ||||||
|     static ParseResult<DataSection> parse(InputStream& stream); |     static ParseResult<DataSection> parse(Core::Stream::Stream& stream); | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     Vector<Data> m_data; |     Vector<Data> m_data; | ||||||
|  | @ -948,7 +972,7 @@ public: | ||||||
| 
 | 
 | ||||||
|     auto& count() const { return m_count; } |     auto& count() const { return m_count; } | ||||||
| 
 | 
 | ||||||
|     static ParseResult<DataCountSection> parse(InputStream& stream); |     static ParseResult<DataCountSection> parse(Core::Stream::Stream& stream); | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     Optional<u32> m_count; |     Optional<u32> m_count; | ||||||
|  | @ -1043,7 +1067,7 @@ public: | ||||||
|     StringView validation_error() const { return *m_validation_error; } |     StringView validation_error() const { return *m_validation_error; } | ||||||
|     void set_validation_error(DeprecatedString error) { m_validation_error = move(error); } |     void set_validation_error(DeprecatedString error) { m_validation_error = move(error); } | ||||||
| 
 | 
 | ||||||
|     static ParseResult<Module> parse(InputStream& stream); |     static ParseResult<Module> parse(Core::Stream::Stream& stream); | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     bool populate_sections(); |     bool populate_sections(); | ||||||
|  |  | ||||||
|  | @ -12,6 +12,7 @@ | ||||||
| #include "WebAssemblyTableObject.h" | #include "WebAssemblyTableObject.h" | ||||||
| #include "WebAssemblyTablePrototype.h" | #include "WebAssemblyTablePrototype.h" | ||||||
| #include <AK/ScopeGuard.h> | #include <AK/ScopeGuard.h> | ||||||
|  | #include <LibCore/MemoryStream.h> | ||||||
| #include <LibJS/Runtime/Array.h> | #include <LibJS/Runtime/Array.h> | ||||||
| #include <LibJS/Runtime/ArrayBuffer.h> | #include <LibJS/Runtime/ArrayBuffer.h> | ||||||
| #include <LibJS/Runtime/BigInt.h> | #include <LibJS/Runtime/BigInt.h> | ||||||
|  | @ -118,13 +119,8 @@ JS::ThrowCompletionOr<size_t> parse_module(JS::VM& vm, JS::Object* buffer_object | ||||||
|     } else { |     } else { | ||||||
|         return vm.throw_completion<JS::TypeError>("Not a BufferSource"); |         return vm.throw_completion<JS::TypeError>("Not a BufferSource"); | ||||||
|     } |     } | ||||||
|     InputMemoryStream stream { data }; |     auto stream = Core::Stream::FixedMemoryStream::construct(data).release_value_but_fixme_should_propagate_errors(); | ||||||
|     auto module_result = Wasm::Module::parse(stream); |     auto module_result = Wasm::Module::parse(*stream); | ||||||
|     ScopeGuard drain_errors { |  | ||||||
|         [&] { |  | ||||||
|             stream.handle_any_error(); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
|     if (module_result.is_error()) { |     if (module_result.is_error()) { | ||||||
|         // FIXME: Throw CompileError instead.
 |         // FIXME: Throw CompileError instead.
 | ||||||
|         return vm.throw_completion<JS::TypeError>(Wasm::parse_error_to_deprecated_string(module_result.error())); |         return vm.throw_completion<JS::TypeError>(Wasm::parse_error_to_deprecated_string(module_result.error())); | ||||||
|  |  | ||||||
|  | @ -252,8 +252,8 @@ static Optional<Wasm::Module> parse(StringView filename) | ||||||
|         return {}; |         return {}; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     InputMemoryStream stream { ReadonlyBytes { result.value()->data(), result.value()->size() } }; |     auto stream = Core::Stream::FixedMemoryStream::construct(ReadonlyBytes { result.value()->data(), result.value()->size() }).release_value_but_fixme_should_propagate_errors(); | ||||||
|     auto parse_result = Wasm::Module::parse(stream); |     auto parse_result = Wasm::Module::parse(*stream); | ||||||
|     if (parse_result.is_error()) { |     if (parse_result.is_error()) { | ||||||
|         warnln("Something went wrong, either the file is invalid, or there's a bug with LibWasm!"); |         warnln("Something went wrong, either the file is invalid, or there's a bug with LibWasm!"); | ||||||
|         warnln("The parse error was {}", Wasm::parse_error_to_deprecated_string(parse_result.error())); |         warnln("The parse error was {}", Wasm::parse_error_to_deprecated_string(parse_result.error())); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Tim Schumacher
						Tim Schumacher