Forráskód Böngészése

AK: Make LEB128 decoding work with `read_value`

Tim Schumacher 2 éve
szülő
commit
47531a42a9

+ 23 - 9
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 };
 };
 
 }

+ 24 - 39
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());
     }
 }

+ 5 - 10
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;
             }
 

+ 8 - 13
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;

+ 1 - 1
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) {

+ 7 - 14
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;

+ 13 - 25
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;
     }

+ 51 - 35
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 };
 

+ 3 - 2
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 };
     }
 };