mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-08-17 09:20:28 +03:00
AK: Don't read past the end in BitmapView::count_in_range()
The current code is factored such that reads to the entirety of the last byte should be dropped. This was relying on the fact that last would be one past the end in that case. Instead of actually reading that byte when it's completely out of bounds of the bitmask, just skip reads that would be invalid. Add more tests to make sure that the behavior is correct for byte aligned reads of byte aligned bitmaps.
This commit is contained in:
parent
b9d65da5c8
commit
73adbb319c
Notes:
sideshowbarker
2024-07-18 17:59:48 +09:00
Author: https://github.com/ADKaster Commit: https://github.com/SerenityOS/serenity/commit/73adbb319ca Pull-request: https://github.com/SerenityOS/serenity/pull/7157 Issue: https://github.com/SerenityOS/serenity/issues/7073 Reviewed-by: https://github.com/linusg Reviewed-by: https://github.com/metmo
@ -52,7 +52,7 @@ public:
|
||||
return 0;
|
||||
|
||||
static const u8 bitmask_first_byte[8] = { 0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80 };
|
||||
static const u8 bitmask_last_byte[8] = { 0x0, 0x1, 0x3, 0x7, 0xF, 0x1F, 0x3F, 0x7F };
|
||||
static const u8 bitmask_last_byte[8] = { 0x00, 0x1, 0x3, 0x7, 0xF, 0x1F, 0x3F, 0x7F };
|
||||
|
||||
size_t count;
|
||||
const u8* first = &m_data[start / 8];
|
||||
@ -64,9 +64,12 @@ public:
|
||||
count = __builtin_popcount(byte);
|
||||
} else {
|
||||
count = __builtin_popcount(byte);
|
||||
byte = *last;
|
||||
byte &= bitmask_last_byte[(start + len) % 8];
|
||||
count += __builtin_popcount(byte);
|
||||
// Don't access *last if it's out of bounds
|
||||
if (last < &m_data[size_in_bytes()]) {
|
||||
byte = *last;
|
||||
byte &= bitmask_last_byte[(start + len) % 8];
|
||||
count += __builtin_popcount(byte);
|
||||
}
|
||||
if (++first < last) {
|
||||
const u32* ptr32 = (const u32*)(((FlatPtr)first + sizeof(u32) - 1) & ~(sizeof(u32) - 1));
|
||||
if ((const u8*)ptr32 > last)
|
||||
|
@ -248,3 +248,31 @@ TEST_CASE(count_in_range)
|
||||
test_with_value(true);
|
||||
test_with_value(false);
|
||||
}
|
||||
|
||||
TEST_CASE(byte_aligned_access)
|
||||
{
|
||||
{
|
||||
Bitmap bitmap(16, true);
|
||||
EXPECT_EQ(bitmap.count_in_range(0, 16, true), 16u);
|
||||
EXPECT_EQ(bitmap.count_in_range(8, 8, true), 8u);
|
||||
EXPECT_EQ(bitmap.count_in_range(0, 8, true), 8u);
|
||||
EXPECT_EQ(bitmap.count_in_range(4, 8, true), 8u);
|
||||
}
|
||||
{
|
||||
Bitmap bitmap(16, false);
|
||||
bitmap.set_range(4, 8, true);
|
||||
EXPECT_EQ(bitmap.count_in_range(0, 16, true), 8u);
|
||||
EXPECT_EQ(bitmap.count_in_range(8, 8, true), 4u);
|
||||
EXPECT_EQ(bitmap.count_in_range(0, 8, true), 4u);
|
||||
EXPECT_EQ(bitmap.count_in_range(4, 8, true), 8u);
|
||||
}
|
||||
{
|
||||
Bitmap bitmap(8, false);
|
||||
bitmap.set(2, true);
|
||||
bitmap.set(4, true);
|
||||
EXPECT_EQ(bitmap.count_in_range(0, 2, true), 0u);
|
||||
EXPECT_EQ(bitmap.count_in_range(0, 4, true), 1u);
|
||||
EXPECT_EQ(bitmap.count_in_range(0, 8, true), 2u);
|
||||
EXPECT_EQ(bitmap.count_in_range(4, 4, true), 1u);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user