diff options
author | Tim Schumacher <timschumi@gmx.de> | 2023-01-30 00:02:38 +0100 |
---|---|---|
committer | Andrew Kaster <andrewdkaster@gmail.com> | 2023-02-04 18:41:27 -0700 |
commit | 47531a42a978859b9b3c7769759ff396c4a02ac2 (patch) | |
tree | 028d21febecb788a370251494aa86cfb5ff9ed90 | |
parent | 787f4d639af6e772c1b6eebe3575ce60ac359f98 (diff) | |
download | serenity-47531a42a978859b9b3c7769759ff396c4a02ac2.zip |
AK: Make LEB128 decoding work with `read_value`
-rw-r--r-- | AK/LEB128.h | 32 | ||||
-rw-r--r-- | Tests/AK/TestLEB128.cpp | 63 | ||||
-rw-r--r-- | Userland/Libraries/LibDebug/Dwarf/AbbreviationsMap.cpp | 15 | ||||
-rw-r--r-- | Userland/Libraries/LibDebug/Dwarf/AddressRanges.cpp | 21 | ||||
-rw-r--r-- | Userland/Libraries/LibDebug/Dwarf/DIE.cpp | 2 | ||||
-rw-r--r-- | Userland/Libraries/LibDebug/Dwarf/DwarfInfo.cpp | 21 | ||||
-rw-r--r-- | Userland/Libraries/LibDebug/Dwarf/LineProgram.cpp | 38 | ||||
-rw-r--r-- | Userland/Libraries/LibWasm/Parser/Parser.cpp | 86 | ||||
-rw-r--r-- | Userland/Libraries/LibWasm/Types.h | 5 |
9 files changed, 135 insertions, 148 deletions
diff --git a/AK/LEB128.h b/AK/LEB128.h index 60ab1153bf..fa01236fc0 100644 --- a/AK/LEB128.h +++ b/AK/LEB128.h @@ -12,11 +12,22 @@ namespace AK { -struct LEB128 { - template<typename ValueType = size_t> - static ErrorOr<void> read_unsigned(AK::Stream& stream, ValueType& result) +template<typename ValueType> +class [[gnu::packed]] LEB128 { +public: + constexpr LEB128() = default; + + constexpr LEB128(ValueType value) + : m_value(value) + { + } + + constexpr operator ValueType() const { return m_value; } + + static ErrorOr<LEB128<ValueType>> read_from_stream(AK::Stream& stream) + requires(Unsigned<ValueType>) { - result = 0; + ValueType result {}; size_t num_bytes = 0; while (true) { if (stream.is_eof()) @@ -39,11 +50,11 @@ struct LEB128 { ++num_bytes; } - return {}; + return LEB128<ValueType> { result }; } - template<typename ValueType = ssize_t> - static ErrorOr<void> read_signed(AK::Stream& stream, ValueType& result) + static ErrorOr<LEB128<ValueType>> read_from_stream(AK::Stream& stream) + requires(Signed<ValueType>) { // Note: We read into a u64 to simplify the parsing logic; // result is range checked into ValueType after parsing. @@ -52,7 +63,7 @@ struct LEB128 { i64 temp = 0; size_t num_bytes = 0; u8 byte = 0; - result = 0; + ValueType result {}; do { if (stream.is_eof()) @@ -87,8 +98,11 @@ struct LEB128 { result = static_cast<ValueType>(temp); - return {}; + return LEB128<ValueType> { result }; } + +private: + ValueType m_value { 0 }; }; } diff --git a/Tests/AK/TestLEB128.cpp b/Tests/AK/TestLEB128.cpp index f16af9bf09..1e7c68024e 100644 --- a/Tests/AK/TestLEB128.cpp +++ b/Tests/AK/TestLEB128.cpp @@ -21,11 +21,11 @@ TEST_CASE(single_byte) buf[0] = i; MUST(stream->seek(0)); - EXPECT(!LEB128::read_unsigned(*stream, output).is_error()); + output = MUST(stream->read_value<LEB128<u32>>()); EXPECT_EQ(output, i); MUST(stream->seek(0)); - EXPECT(!LEB128::read_signed(*stream, output_signed).is_error()); + output_signed = MUST(stream->read_value<LEB128<i32>>()); EXPECT_EQ(output_signed, i); } @@ -34,11 +34,11 @@ TEST_CASE(single_byte) buf[0] = i; MUST(stream->seek(0)); - EXPECT(!LEB128::read_unsigned(*stream, output).is_error()); + output = MUST(stream->read_value<LEB128<u32>>()); EXPECT_EQ(output, i); MUST(stream->seek(0)); - EXPECT(!LEB128::read_signed(*stream, output_signed).is_error()); + output_signed = MUST(stream->read_value<LEB128<i32>>()); EXPECT_EQ(output_signed, (i | (-1 & (~0x3F)))); } // MSB set, but input too short @@ -46,10 +46,10 @@ TEST_CASE(single_byte) buf[0] = static_cast<u8>(i); MUST(stream->seek(0)); - EXPECT(LEB128::read_unsigned(*stream, output).is_error()); + EXPECT(stream->read_value<LEB128<u32>>().is_error()); MUST(stream->seek(0)); - EXPECT(LEB128::read_signed(*stream, output_signed).is_error()); + EXPECT(stream->read_value<LEB128<i32>>().is_error()); } } @@ -69,11 +69,11 @@ TEST_CASE(two_bytes) buf[1] = j; MUST(stream->seek(0)); - EXPECT(!LEB128::read_unsigned(*stream, output).is_error()); + output = MUST(stream->read_value<LEB128<u32>>()); EXPECT_EQ(output, (static_cast<u32>(j) << 7) + (i & 0x7F)); MUST(stream->seek(0)); - EXPECT(!LEB128::read_signed(*stream, output_signed).is_error()); + output_signed = MUST(stream->read_value<LEB128<i32>>()); EXPECT_EQ(output_signed, (static_cast<i32>(j) << 7) + (i & 0x7F)); } @@ -82,11 +82,11 @@ TEST_CASE(two_bytes) buf[1] = j; MUST(stream->seek(0)); - EXPECT(!LEB128::read_unsigned(*stream, output).is_error()); + output = MUST(stream->read_value<LEB128<u32>>()); EXPECT_EQ(output, (static_cast<u32>(j) << 7) + (i & 0x7F)); MUST(stream->seek(0)); - EXPECT(!LEB128::read_signed(*stream, output_signed).is_error()); + output_signed = MUST(stream->read_value<LEB128<i32>>()); EXPECT_EQ(output_signed, ((static_cast<i32>(j) << 7) + (i & 0x7F)) | (-1 & (~0x3FFF))); } @@ -95,10 +95,10 @@ TEST_CASE(two_bytes) buf[1] = static_cast<u8>(j); MUST(stream->seek(0)); - EXPECT(LEB128::read_unsigned(*stream, output).is_error()); + EXPECT(stream->read_value<LEB128<u32>>().is_error()); MUST(stream->seek(0)); - EXPECT(LEB128::read_signed(*stream, output_signed).is_error()); + EXPECT(stream->read_value<LEB128<i32>>().is_error()); } } } @@ -107,27 +107,22 @@ TEST_CASE(overflow_sizeof_output_unsigned) { u8 u32_max_plus_one[] = { 0x80, 0x80, 0x80, 0x80, 0x10 }; { - u32 out = 0; auto stream = MUST(FixedMemoryStream::construct(ReadonlyBytes { u32_max_plus_one, sizeof(u32_max_plus_one) })); - EXPECT(LEB128::read_unsigned(*stream, out).is_error()); - EXPECT_EQ(out, 0u); + EXPECT(stream->read_value<LEB128<u32>>().is_error()); - u64 out64 = 0; MUST(stream->seek(0)); - EXPECT(!LEB128::read_unsigned(*stream, out64).is_error()); + u64 out64 = MUST(stream->read_value<LEB128<u64>>()); EXPECT_EQ(out64, static_cast<u64>(NumericLimits<u32>::max()) + 1); } u8 u32_max[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0x0F }; { - u32 out = 0; auto stream = MUST(FixedMemoryStream::construct(ReadonlyBytes { u32_max, sizeof(u32_max) })); - EXPECT(!LEB128::read_unsigned(*stream, out).is_error()); + u32 out = MUST(stream->read_value<LEB128<u32>>()); EXPECT_EQ(out, NumericLimits<u32>::max()); - u64 out64 = 0; MUST(stream->seek(0)); - EXPECT(!LEB128::read_unsigned(*stream, out64).is_error()); + u64 out64 = MUST(stream->read_value<LEB128<u64>>()); EXPECT_EQ(out64, NumericLimits<u32>::max()); } } @@ -136,53 +131,43 @@ TEST_CASE(overflow_sizeof_output_signed) { u8 i32_max_plus_one[] = { 0x80, 0x80, 0x80, 0x80, 0x08 }; { - i32 out = 0; auto stream = MUST(FixedMemoryStream::construct(ReadonlyBytes { i32_max_plus_one, sizeof(i32_max_plus_one) })); - EXPECT(LEB128::read_signed(*stream, out).is_error()); - EXPECT_EQ(out, 0); + EXPECT(stream->read_value<LEB128<i32>>().is_error()); - i64 out64 = 0; MUST(stream->seek(0)); - EXPECT(!LEB128::read_signed(*stream, out64).is_error()); + i64 out64 = MUST(stream->read_value<LEB128<i64>>()); EXPECT_EQ(out64, static_cast<i64>(NumericLimits<i32>::max()) + 1); } u8 i32_max[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0x07 }; { - i32 out = 0; auto stream = MUST(FixedMemoryStream::construct(ReadonlyBytes { i32_max, sizeof(i32_max) })); - EXPECT(!LEB128::read_signed(*stream, out).is_error()); + i32 out = MUST(stream->read_value<LEB128<i32>>()); EXPECT_EQ(out, NumericLimits<i32>::max()); - i64 out64 = 0; MUST(stream->seek(0)); - EXPECT(!LEB128::read_signed(*stream, out64).is_error()); + i64 out64 = MUST(stream->read_value<LEB128<i64>>()); EXPECT_EQ(out64, NumericLimits<i32>::max()); } u8 i32_min_minus_one[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0x77 }; { - i32 out = 0; auto stream = MUST(FixedMemoryStream::construct(ReadonlyBytes { i32_min_minus_one, sizeof(i32_min_minus_one) })); - EXPECT(LEB128::read_signed(*stream, out).is_error()); - EXPECT_EQ(out, 0); + EXPECT(stream->read_value<LEB128<i32>>().is_error()); - i64 out64 = 0; MUST(stream->seek(0)); - EXPECT(!LEB128::read_signed(*stream, out64).is_error()); + i64 out64 = MUST(stream->read_value<LEB128<i64>>()); EXPECT_EQ(out64, static_cast<i64>(NumericLimits<i32>::min()) - 1); } u8 i32_min[] = { 0x80, 0x80, 0x80, 0x80, 0x78 }; { - i32 out = 0; auto stream = MUST(FixedMemoryStream::construct(ReadonlyBytes { i32_min, sizeof(i32_min) })); - EXPECT(!LEB128::read_signed(*stream, out).is_error()); + i32 out = MUST(stream->read_value<LEB128<i32>>()); EXPECT_EQ(out, NumericLimits<i32>::min()); - i64 out64 = 0; MUST(stream->seek(0)); - EXPECT(!LEB128::read_signed(*stream, out64).is_error()); + i64 out64 = MUST(stream->read_value<LEB128<i64>>()); EXPECT_EQ(out64, NumericLimits<i32>::min()); } } diff --git a/Userland/Libraries/LibDebug/Dwarf/AbbreviationsMap.cpp b/Userland/Libraries/LibDebug/Dwarf/AbbreviationsMap.cpp index 13ad046248..e8c263ffa6 100644 --- a/Userland/Libraries/LibDebug/Dwarf/AbbreviationsMap.cpp +++ b/Userland/Libraries/LibDebug/Dwarf/AbbreviationsMap.cpp @@ -25,15 +25,13 @@ ErrorOr<void> AbbreviationsMap::populate_map() TRY(abbreviation_stream->discard(m_offset)); while (!abbreviation_stream->is_eof()) { - size_t abbreviation_code = 0; - TRY(LEB128::read_unsigned(*abbreviation_stream, abbreviation_code)); + size_t abbreviation_code = TRY(abbreviation_stream->read_value<LEB128<size_t>>()); // An abbreviation code of 0 marks the end of the // abbreviations for a given compilation unit if (abbreviation_code == 0) break; - size_t tag {}; - TRY(LEB128::read_unsigned(*abbreviation_stream, tag)); + size_t tag = TRY(abbreviation_stream->read_value<LEB128<size_t>>()); auto has_children = TRY(abbreviation_stream->read_value<u8>()); @@ -43,17 +41,14 @@ ErrorOr<void> AbbreviationsMap::populate_map() AttributeSpecification current_attribute_specification {}; do { - size_t attribute_value = 0; - size_t form_value = 0; - TRY(LEB128::read_unsigned(*abbreviation_stream, attribute_value)); - TRY(LEB128::read_unsigned(*abbreviation_stream, form_value)); + size_t attribute_value = TRY(abbreviation_stream->read_value<LEB128<size_t>>()); + size_t form_value = TRY(abbreviation_stream->read_value<LEB128<size_t>>()); current_attribute_specification.attribute = static_cast<Attribute>(attribute_value); current_attribute_specification.form = static_cast<AttributeDataForm>(form_value); if (current_attribute_specification.form == AttributeDataForm::ImplicitConst) { - ssize_t data_value; - TRY(LEB128::read_signed(*abbreviation_stream, data_value)); + ssize_t data_value = TRY(abbreviation_stream->read_value<LEB128<ssize_t>>()); current_attribute_specification.value = data_value; } diff --git a/Userland/Libraries/LibDebug/Dwarf/AddressRanges.cpp b/Userland/Libraries/LibDebug/Dwarf/AddressRanges.cpp index c43ad1e468..b444eaa229 100644 --- a/Userland/Libraries/LibDebug/Dwarf/AddressRanges.cpp +++ b/Userland/Libraries/LibDebug/Dwarf/AddressRanges.cpp @@ -30,8 +30,7 @@ ErrorOr<void> AddressRangesV5::for_each_range(Function<void(Range)> callback) break; } case RangeListEntryType::BaseAddressX: { - FlatPtr index; - TRY(LEB128::read_unsigned(*m_range_lists_stream, index)); + FlatPtr index = TRY(m_range_lists_stream->read_value<LEB128<FlatPtr>>()); current_base_address = TRY(m_compilation_unit.get_address(index)); break; } @@ -44,30 +43,26 @@ ErrorOr<void> AddressRangesV5::for_each_range(Function<void(Range)> callback) if (!base_address.has_value()) return Error::from_string_literal("Expected base_address for rangelist"); - size_t start_offset, end_offset; - TRY(LEB128::read_unsigned(*m_range_lists_stream, start_offset)); - TRY(LEB128::read_unsigned(*m_range_lists_stream, end_offset)); + size_t start_offset = TRY(m_range_lists_stream->read_value<LEB128<size_t>>()); + size_t end_offset = TRY(m_range_lists_stream->read_value<LEB128<size_t>>()); callback(Range { start_offset + *base_address, end_offset + *base_address }); break; } case RangeListEntryType::StartLength: { auto start = TRY(m_range_lists_stream->read_value<FlatPtr>()); - size_t length; - TRY(LEB128::read_unsigned(*m_range_lists_stream, length)); + size_t length = TRY(m_range_lists_stream->read_value<LEB128<size_t>>()); callback(Range { start, start + length }); break; } case RangeListEntryType::StartXEndX: { - size_t start, end; - TRY(LEB128::read_unsigned(*m_range_lists_stream, start)); - TRY(LEB128::read_unsigned(*m_range_lists_stream, end)); + size_t start = TRY(m_range_lists_stream->read_value<LEB128<size_t>>()); + size_t end = TRY(m_range_lists_stream->read_value<LEB128<size_t>>()); callback(Range { TRY(m_compilation_unit.get_address(start)), TRY(m_compilation_unit.get_address(end)) }); break; } case RangeListEntryType::StartXLength: { - size_t start, length; - TRY(LEB128::read_unsigned(*m_range_lists_stream, start)); - TRY(LEB128::read_unsigned(*m_range_lists_stream, length)); + size_t start = TRY(m_range_lists_stream->read_value<LEB128<size_t>>()); + size_t length = TRY(m_range_lists_stream->read_value<LEB128<size_t>>()); auto start_addr = TRY(m_compilation_unit.get_address(start)); callback(Range { start_addr, start_addr + length }); break; diff --git a/Userland/Libraries/LibDebug/Dwarf/DIE.cpp b/Userland/Libraries/LibDebug/Dwarf/DIE.cpp index 05b6849daf..a9e0cef979 100644 --- a/Userland/Libraries/LibDebug/Dwarf/DIE.cpp +++ b/Userland/Libraries/LibDebug/Dwarf/DIE.cpp @@ -26,7 +26,7 @@ ErrorOr<void> DIE::rehydrate_from(u32 offset, Optional<u32> parent_offset) auto stream = TRY(FixedMemoryStream::construct(m_compilation_unit.dwarf_info().debug_info_data())); // Note: We can't just slice away from the input data here, since get_attribute_value will try to recover the original offset using seek(). TRY(stream->seek(m_offset)); - TRY(LEB128::read_unsigned(*stream, m_abbreviation_code)); + m_abbreviation_code = TRY(stream->read_value<LEB128<size_t>>()); m_data_offset = TRY(stream->tell()); if (m_abbreviation_code == 0) { diff --git a/Userland/Libraries/LibDebug/Dwarf/DwarfInfo.cpp b/Userland/Libraries/LibDebug/Dwarf/DwarfInfo.cpp index 3f369944bd..b4b519cdaf 100644 --- a/Userland/Libraries/LibDebug/Dwarf/DwarfInfo.cpp +++ b/Userland/Libraries/LibDebug/Dwarf/DwarfInfo.cpp @@ -120,15 +120,13 @@ ErrorOr<AttributeValue> DwarfInfo::get_attribute_value(AttributeDataForm form, s break; } case AttributeDataForm::SData: { - i64 data; - TRY(LEB128::read_signed(debug_info_stream, data)); + i64 data = TRY(debug_info_stream.read_value<LEB128<i64>>()); value.m_type = AttributeValue::Type::SignedNumber; value.m_data.as_signed = data; break; } case AttributeDataForm::UData: { - u64 data; - TRY(LEB128::read_unsigned(debug_info_stream, data)); + u64 data = TRY(debug_info_stream.read_value<LEB128<u64>>()); value.m_type = AttributeValue::Type::UnsignedNumber; value.m_data.as_unsigned = data; break; @@ -169,8 +167,7 @@ ErrorOr<AttributeValue> DwarfInfo::get_attribute_value(AttributeDataForm form, s break; } case AttributeDataForm::ExprLoc: { - size_t length; - TRY(LEB128::read_unsigned(debug_info_stream, length)); + size_t length = TRY(debug_info_stream.read_value<LEB128<size_t>>()); value.m_type = AttributeValue::Type::DwarfExpression; TRY(assign_raw_bytes_value(length)); break; @@ -202,8 +199,7 @@ ErrorOr<AttributeValue> DwarfInfo::get_attribute_value(AttributeDataForm form, s } case AttributeDataForm::Block: { value.m_type = AttributeValue::Type::RawBytes; - size_t length; - TRY(LEB128::read_unsigned(debug_info_stream, length)); + size_t length = TRY(debug_info_stream.read_value<LEB128<size_t>>()); TRY(assign_raw_bytes_value(length)); break; } @@ -240,8 +236,7 @@ ErrorOr<AttributeValue> DwarfInfo::get_attribute_value(AttributeDataForm form, s break; } case AttributeDataForm::StrX: { - size_t index; - TRY(LEB128::read_unsigned(debug_info_stream, index)); + size_t index = TRY(debug_info_stream.read_value<LEB128<size_t>>()); value.m_type = AttributeValue::Type::String; value.m_data.as_unsigned = index; break; @@ -265,15 +260,13 @@ ErrorOr<AttributeValue> DwarfInfo::get_attribute_value(AttributeDataForm form, s break; } case AttributeDataForm::AddrX: { - size_t index; - TRY(LEB128::read_unsigned(debug_info_stream, index)); + size_t index = TRY(debug_info_stream.read_value<LEB128<size_t>>()); value.m_type = AttributeValue::Type::Address; value.m_data.as_unsigned = index; break; } case AttributeDataForm::RngListX: { - size_t index; - TRY(LEB128::read_unsigned(debug_info_stream, index)); + size_t index = TRY(debug_info_stream.read_value<LEB128<size_t>>()); value.m_type = AttributeValue::Type::UnsignedNumber; value.m_data.as_unsigned = index; break; diff --git a/Userland/Libraries/LibDebug/Dwarf/LineProgram.cpp b/Userland/Libraries/LibDebug/Dwarf/LineProgram.cpp index 16c5bc25ed..fcd591ef03 100644 --- a/Userland/Libraries/LibDebug/Dwarf/LineProgram.cpp +++ b/Userland/Libraries/LibDebug/Dwarf/LineProgram.cpp @@ -44,17 +44,14 @@ ErrorOr<void> LineProgram::parse_path_entries(Function<void(PathEntry& entry)> c Vector<PathEntryFormat> format_descriptions; for (u8 i = 0; i < path_entry_format_count; i++) { - UnderlyingType<ContentType> content_type; - TRY(LEB128::read_unsigned(m_stream, content_type)); + UnderlyingType<ContentType> content_type = TRY(m_stream.read_value<LEB128<UnderlyingType<ContentType>>>()); - UnderlyingType<AttributeDataForm> data_form; - TRY(LEB128::read_unsigned(m_stream, data_form)); + UnderlyingType<AttributeDataForm> data_form = TRY(m_stream.read_value<LEB128<UnderlyingType<AttributeDataForm>>>()); format_descriptions.empend(static_cast<ContentType>(content_type), static_cast<AttributeDataForm>(data_form)); } - size_t paths_count = 0; - TRY(LEB128::read_unsigned(m_stream, paths_count)); + size_t paths_count = TRY(m_stream.read_value<LEB128<size_t>>()); for (size_t i = 0; i < paths_count; i++) { PathEntry entry; @@ -85,11 +82,9 @@ ErrorOr<void> LineProgram::parse_path_entries(Function<void(PathEntry& entry)> c PathEntry entry; entry.path = path; if (list_type == PathListType::Filenames) { - size_t directory_index = 0; - TRY(LEB128::read_unsigned(m_stream, directory_index)); - size_t _unused = 0; - TRY(LEB128::read_unsigned(m_stream, _unused)); // skip modification time - TRY(LEB128::read_unsigned(m_stream, _unused)); // skip file size + size_t directory_index = TRY(m_stream.read_value<LEB128<size_t>>()); + TRY(m_stream.read_value<LEB128<size_t>>()); // skip modification time + TRY(m_stream.read_value<LEB128<size_t>>()); // skip file size entry.directory_index = directory_index; dbgln_if(DWARF_DEBUG, "file: {}, directory index: {}", path, directory_index); } @@ -157,8 +152,7 @@ void LineProgram::reset_registers() ErrorOr<void> LineProgram::handle_extended_opcode() { - size_t length = 0; - TRY(LEB128::read_unsigned(m_stream, length)); + size_t length = TRY(m_stream.read_value<LEB128<size_t>>()); auto sub_opcode = TRY(m_stream.read_value<u8>()); @@ -176,8 +170,7 @@ ErrorOr<void> LineProgram::handle_extended_opcode() } case ExtendedOpcodes::SetDiscriminator: { dbgln_if(DWARF_DEBUG, "SetDiscriminator"); - size_t discriminator; - TRY(LEB128::read_unsigned(m_stream, discriminator)); + [[maybe_unused]] size_t discriminator = TRY(m_stream.read_value<LEB128<size_t>>()); break; } default: @@ -195,16 +188,14 @@ ErrorOr<void> LineProgram::handle_standard_opcode(u8 opcode) break; } case StandardOpcodes::AdvancePc: { - size_t operand = 0; - TRY(LEB128::read_unsigned(m_stream, operand)); + size_t operand = TRY(m_stream.read_value<LEB128<size_t>>()); size_t delta = operand * m_unit_header.min_instruction_length(); dbgln_if(DWARF_DEBUG, "AdvancePC by: {} to: {:p}", delta, m_address + delta); m_address += delta; break; } case StandardOpcodes::SetFile: { - size_t new_file_index = 0; - TRY(LEB128::read_unsigned(m_stream, new_file_index)); + size_t new_file_index = TRY(m_stream.read_value<LEB128<size_t>>()); dbgln_if(DWARF_DEBUG, "SetFile: new file index: {}", new_file_index); m_file_index = new_file_index; break; @@ -212,14 +203,12 @@ ErrorOr<void> LineProgram::handle_standard_opcode(u8 opcode) case StandardOpcodes::SetColumn: { // not implemented dbgln_if(DWARF_DEBUG, "SetColumn"); - size_t new_column; - TRY(LEB128::read_unsigned(m_stream, new_column)); + [[maybe_unused]] size_t new_column = TRY(m_stream.read_value<LEB128<size_t>>()); break; } case StandardOpcodes::AdvanceLine: { - ssize_t line_delta; - TRY(LEB128::read_signed(m_stream, line_delta)); + ssize_t line_delta = TRY(m_stream.read_value<LEB128<ssize_t>>()); VERIFY(line_delta >= 0 || m_line >= (size_t)(-line_delta)); m_line += line_delta; dbgln_if(DWARF_DEBUG, "AdvanceLine: {}", m_line); @@ -239,8 +228,7 @@ ErrorOr<void> LineProgram::handle_standard_opcode(u8 opcode) break; } case StandardOpcodes::SetIsa: { - size_t isa; - TRY(LEB128::read_unsigned(m_stream, isa)); + size_t isa = TRY(m_stream.read_value<LEB128<size_t>>()); dbgln_if(DWARF_DEBUG, "SetIsa: {}", isa); break; } diff --git a/Userland/Libraries/LibWasm/Parser/Parser.cpp b/Userland/Libraries/LibWasm/Parser/Parser.cpp index a9e76b5d84..51f72d99e1 100644 --- a/Userland/Libraries/LibWasm/Parser/Parser.cpp +++ b/Userland/Libraries/LibWasm/Parser/Parser.cpp @@ -26,9 +26,10 @@ static auto parse_vector(AK::Stream& stream) ScopeLogger<WASM_BINPARSER_DEBUG> logger; if constexpr (requires { T::parse(stream); }) { using ResultT = typename decltype(T::parse(stream))::ValueType; - size_t count; - if (LEB128::read_unsigned(stream, count).is_error()) + auto count_or_error = stream.read_value<LEB128<size_t>>(); + if (count_or_error.is_error()) return ParseResult<Vector<ResultT>> { with_eof_check(stream, ParseError::ExpectedSize) }; + size_t count = count_or_error.release_value(); Vector<ResultT> entries; for (size_t i = 0; i < count; ++i) { @@ -39,21 +40,24 @@ static auto parse_vector(AK::Stream& stream) } return ParseResult<Vector<ResultT>> { move(entries) }; } else { - size_t count; - if (LEB128::read_unsigned(stream, count).is_error()) + auto count_or_error = stream.read_value<LEB128<size_t>>(); + if (count_or_error.is_error()) return ParseResult<Vector<T>> { with_eof_check(stream, ParseError::ExpectedSize) }; + size_t count = count_or_error.release_value(); Vector<T> entries; for (size_t i = 0; i < count; ++i) { if constexpr (IsSame<T, size_t>) { - size_t value; - if (LEB128::read_unsigned(stream, value).is_error()) + auto value_or_error = stream.read_value<LEB128<size_t>>(); + if (value_or_error.is_error()) return ParseResult<Vector<T>> { with_eof_check(stream, ParseError::ExpectedSize) }; + size_t value = value_or_error.release_value(); entries.append(value); } else if constexpr (IsSame<T, ssize_t>) { - ssize_t value; - if (LEB128::read_signed(stream, value).is_error()) + auto value_or_error = stream.read_value<LEB128<ssize_t>>(); + if (value_or_error.is_error()) return ParseResult<Vector<T>> { with_eof_check(stream, ParseError::ExpectedSize) }; + ssize_t value = value_or_error.release_value(); entries.append(value); } else if constexpr (IsSame<T, u8>) { if (count > Constants::max_allowed_vector_size) @@ -186,16 +190,17 @@ ParseResult<Limits> Limits::parse(AK::Stream& stream) if (flag > 1) return with_eof_check(stream, ParseError::InvalidTag); - size_t min; - if (LEB128::read_unsigned(stream, min).is_error()) + auto min_or_error = stream.read_value<LEB128<size_t>>(); + if (min_or_error.is_error()) return with_eof_check(stream, ParseError::ExpectedSize); + size_t min = min_or_error.release_value(); Optional<u32> max; if (flag) { - size_t value; - if (LEB128::read_unsigned(stream, value).is_error()) + auto value_or_error = stream.read_value<LEB128<size_t>>(); + if (value_or_error.is_error()) return with_eof_check(stream, ParseError::ExpectedSize); - max = value; + max = value_or_error.release_value(); } return Limits { static_cast<u32>(min), move(max) }; @@ -263,9 +268,10 @@ ParseResult<BlockType> BlockType::parse(AK::Stream& stream) ReconsumableStream new_stream { stream }; new_stream.unread({ &kind, 1 }); - ssize_t index_value; - if (LEB128::read_signed(new_stream, index_value).is_error()) + auto index_value_or_error = stream.read_value<LEB128<ssize_t>>(); + if (index_value_or_error.is_error()) return with_eof_check(stream, ParseError::ExpectedIndex); + ssize_t index_value = index_value_or_error.release_value(); if (index_value < 0) { dbgln("Invalid type index {}", index_value); @@ -408,13 +414,15 @@ ParseResult<Vector<Instruction>> Instruction::parse(AK::Stream& stream, Instruct case Instructions::i64_store16.value(): case Instructions::i64_store32.value(): { // op (align offset) - size_t align; - if (LEB128::read_unsigned(stream, align).is_error()) + auto align_or_error = stream.read_value<LEB128<size_t>>(); + if (align_or_error.is_error()) return with_eof_check(stream, ParseError::InvalidInput); + size_t align = align_or_error.release_value(); - size_t offset; - if (LEB128::read_unsigned(stream, offset).is_error()) + auto offset_or_error = stream.read_value<LEB128<size_t>>(); + if (offset_or_error.is_error()) return with_eof_check(stream, ParseError::InvalidInput); + size_t offset = offset_or_error.release_value(); resulting_instructions.append(Instruction { opcode, MemoryArgument { static_cast<u32>(align), static_cast<u32>(offset) } }); break; @@ -456,18 +464,20 @@ ParseResult<Vector<Instruction>> Instruction::parse(AK::Stream& stream, Instruct break; } case Instructions::i32_const.value(): { - i32 value; - if (LEB128::read_signed(stream, value).is_error()) + auto value_or_error = stream.read_value<LEB128<i32>>(); + if (value_or_error.is_error()) return with_eof_check(stream, ParseError::ExpectedSignedImmediate); + i32 value = value_or_error.release_value(); resulting_instructions.append(Instruction { opcode, value }); break; } case Instructions::i64_const.value(): { // op literal - i64 value; - if (LEB128::read_signed(stream, value).is_error()) + auto value_or_error = stream.read_value<LEB128<i64>>(); + if (value_or_error.is_error()) return with_eof_check(stream, ParseError::ExpectedSignedImmediate); + i64 value = value_or_error.release_value(); resulting_instructions.append(Instruction { opcode, value }); break; @@ -665,9 +675,10 @@ ParseResult<Vector<Instruction>> Instruction::parse(AK::Stream& stream, Instruct break; case 0xfc: { // These are multibyte instructions. - u32 selector; - if (LEB128::read_unsigned(stream, selector).is_error()) + auto selector_or_error = stream.read_value<LEB128<u32>>(); + if (selector_or_error.is_error()) return with_eof_check(stream, ParseError::InvalidInput); + u32 selector = selector_or_error.release_value(); switch (selector) { case Instructions::i32_trunc_sat_f32_s_second: case Instructions::i32_trunc_sat_f32_u_second: @@ -942,9 +953,10 @@ ParseResult<ExportSection::Export> ExportSection::Export::parse(AK::Stream& stre auto tag = tag_or_error.release_value(); - size_t index; - if (LEB128::read_unsigned(stream, index).is_error()) + auto index_or_error = stream.read_value<LEB128<size_t>>(); + if (index_or_error.is_error()) return with_eof_check(stream, ParseError::ExpectedIndex); + size_t index = index_or_error.release_value(); switch (tag) { case Constants::extern_function_tag: @@ -1138,9 +1150,10 @@ ParseResult<ElementSection> ElementSection::parse(AK::Stream& stream) ParseResult<Locals> Locals::parse(AK::Stream& stream) { ScopeLogger<WASM_BINPARSER_DEBUG> logger("Locals"sv); - size_t count; - if (LEB128::read_unsigned(stream, count).is_error()) + auto count_or_error = stream.read_value<LEB128<size_t>>(); + if (count_or_error.is_error()) return with_eof_check(stream, ParseError::InvalidSize); + size_t count = count_or_error.release_value(); if (count > Constants::max_allowed_function_locals_per_type) return with_eof_check(stream, ParseError::HugeAllocationRequested); @@ -1167,9 +1180,10 @@ ParseResult<CodeSection::Func> CodeSection::Func::parse(AK::Stream& stream) ParseResult<CodeSection::Code> CodeSection::Code::parse(AK::Stream& stream) { ScopeLogger<WASM_BINPARSER_DEBUG> logger("Code"sv); - size_t size; - if (LEB128::read_unsigned(stream, size).is_error()) + auto size_or_error = stream.read_value<LEB128<size_t>>(); + if (size_or_error.is_error()) return with_eof_check(stream, ParseError::InvalidSize); + size_t size = size_or_error.release_value(); auto constrained_stream = ConstrainedStream { stream, size }; @@ -1244,14 +1258,15 @@ ParseResult<DataSection> DataSection::parse(AK::Stream& stream) ParseResult<DataCountSection> DataCountSection::parse([[maybe_unused]] AK::Stream& stream) { ScopeLogger<WASM_BINPARSER_DEBUG> logger("DataCountSection"sv); - u32 value; - if (LEB128::read_unsigned(stream, value).is_error()) { + auto value_or_error = stream.read_value<LEB128<u32>>(); + if (value_or_error.is_error()) { if (stream.is_eof()) { // The section simply didn't contain anything. return DataCountSection { {} }; } return ParseError::ExpectedSize; } + u32 value = value_or_error.release_value(); return DataCountSection { value }; } @@ -1280,9 +1295,10 @@ ParseResult<Module> Module::parse(AK::Stream& stream) auto section_id = section_id_or_error.release_value(); - size_t section_size; - if (LEB128::read_unsigned(stream, section_size).is_error()) + auto section_size_or_error = stream.read_value<LEB128<size_t>>(); + if (section_size_or_error.is_error()) return with_eof_check(stream, ParseError::ExpectedSize); + size_t section_size = section_size_or_error.release_value(); auto section_stream = ConstrainedStream { stream, section_size }; diff --git a/Userland/Libraries/LibWasm/Types.h b/Userland/Libraries/LibWasm/Types.h index 61da9d428f..edab97c839 100644 --- a/Userland/Libraries/LibWasm/Types.h +++ b/Userland/Libraries/LibWasm/Types.h @@ -65,9 +65,10 @@ template<typename T> struct GenericIndexParser { static ParseResult<T> parse(AK::Stream& stream) { - size_t value; - if (LEB128::read_unsigned(stream, value).is_error()) + auto value_or_error = stream.read_value<LEB128<size_t>>(); + if (value_or_error.is_error()) return with_eof_check(stream, ParseError::ExpectedIndex); + size_t value = value_or_error.release_value(); return T { value }; } }; |