1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 20:47:45 +00:00

AK: Handle LEB128 encoded values that are too large for the result type

Previously, we would go crazy and shift things way out of bounds.
Add tests to verify that the decoding algorithm is safe around the
limits of the result type.
This commit is contained in:
Andrew Kaster 2021-05-30 16:12:11 -06:00 committed by Ali Mohammad Pur
parent c59cf0da07
commit 0af192ff8d
2 changed files with 130 additions and 7 deletions

View file

@ -6,6 +6,7 @@
#include <AK/LEB128.h>
#include <AK/MemoryStream.h>
#include <AK/NumericLimits.h>
#include <LibTest/TestCase.h>
TEST_CASE(single_byte)
@ -113,3 +114,99 @@ TEST_CASE(two_bytes)
}
}
}
TEST_CASE(overflow_sizeof_output_unsigned)
{
u8 u32_max_plus_one[] = { 0x80, 0x80, 0x80, 0x80, 0x10 };
{
u32 out = 0;
InputMemoryStream stream({ u32_max_plus_one, sizeof(u32_max_plus_one) });
EXPECT(!LEB128::read_unsigned(stream, out));
EXPECT_EQ(out, 0u);
EXPECT(!stream.handle_any_error());
u64 out64 = 0;
stream.seek(0);
EXPECT(LEB128::read_unsigned(stream, out64));
EXPECT_EQ(out64, static_cast<u64>(NumericLimits<u32>::max()) + 1);
EXPECT(!stream.handle_any_error());
}
u8 u32_max[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0x0F };
{
u32 out = 0;
InputMemoryStream stream({ u32_max, sizeof(u32_max) });
EXPECT(LEB128::read_unsigned(stream, out));
EXPECT_EQ(out, NumericLimits<u32>::max());
EXPECT(!stream.handle_any_error());
u64 out64 = 0;
stream.seek(0);
EXPECT(LEB128::read_unsigned(stream, out64));
EXPECT_EQ(out64, NumericLimits<u32>::max());
EXPECT(!stream.handle_any_error());
}
}
TEST_CASE(overflow_sizeof_output_signed)
{
u8 i32_max_plus_one[] = { 0x80, 0x80, 0x80, 0x80, 0x08 };
{
i32 out = 0;
InputMemoryStream stream({ i32_max_plus_one, sizeof(i32_max_plus_one) });
EXPECT(!LEB128::read_signed(stream, out));
EXPECT_EQ(out, 0);
EXPECT(!stream.handle_any_error());
i64 out64 = 0;
stream.seek(0);
EXPECT(LEB128::read_signed(stream, out64));
EXPECT_EQ(out64, static_cast<i64>(NumericLimits<i32>::max()) + 1);
EXPECT(!stream.handle_any_error());
}
u8 i32_max[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0x07 };
{
i32 out = 0;
InputMemoryStream stream({ i32_max, sizeof(i32_max) });
EXPECT(LEB128::read_signed(stream, out));
EXPECT_EQ(out, NumericLimits<i32>::max());
EXPECT(!stream.handle_any_error());
i64 out64 = 0;
stream.seek(0);
EXPECT(LEB128::read_signed(stream, out64));
EXPECT_EQ(out64, NumericLimits<i32>::max());
EXPECT(!stream.handle_any_error());
}
u8 i32_min_minus_one[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0x77 };
{
i32 out = 0;
InputMemoryStream stream({ i32_min_minus_one, sizeof(i32_min_minus_one) });
EXPECT(!LEB128::read_signed(stream, out));
EXPECT_EQ(out, 0);
EXPECT(!stream.handle_any_error());
i64 out64 = 0;
stream.seek(0);
EXPECT(LEB128::read_signed(stream, out64));
EXPECT_EQ(out64, static_cast<i64>(NumericLimits<i32>::min()) - 1);
EXPECT(!stream.handle_any_error());
}
u8 i32_min[] = { 0x80, 0x80, 0x80, 0x80, 0x78 };
{
i32 out = 0;
InputMemoryStream stream({ i32_min, sizeof(i32_min) });
EXPECT(LEB128::read_signed(stream, out));
EXPECT_EQ(out, NumericLimits<i32>::min());
EXPECT(!stream.handle_any_error());
i64 out64 = 0;
stream.seek(0);
EXPECT(LEB128::read_signed(stream, out64));
EXPECT_EQ(out64, NumericLimits<i32>::min());
EXPECT(!stream.handle_any_error());
}
}