LibGfx: Reject a BMP V5 ICC profile offset that points out of bounds

Problem: A BMP V5 image whose embedded ICC profile offset points past
the end of the file triggers an OOB read.

Cause: The bounds check summed the profile offset, the file-header size,
and the profile size in 32-bit arithmetic. So, a large offset (e.g.
0xfffffff0) wraps the sum back into range and passes the check. The
decoder then returns a span pointing far past the end of the file.

Fix: Compute the sum in 64 bits — so an out-of-bounds offset can no
longer wrap, and the profile’s rejected.

Fixes: https://github.com/LadybirdBrowser/ladybird/issues/9967
This commit is contained in:
sideshowbarker 2026-06-14 20:07:35 +09:00 committed by sideshowbarker
parent 9bde8a5c88
commit 602e7fe2bd
3 changed files with 9 additions and 1 deletions

View file

@ -1571,7 +1571,7 @@ ErrorOr<Optional<ReadonlyBytes>> BMPImageDecoderPlugin::icc_data()
// FIXME: Do something with v5.intent (which has a GamutMappingIntent value).
u8 header_size = m_context->is_included_in_ico ? 0 : bmp_header_size;
if (v5.profile_data + header_size + v5.profile_size > m_context->file_size)
if (static_cast<u64>(v5.profile_data) + header_size + v5.profile_size > m_context->file_size)
return Error::from_string_literal("BMPImageDecoderPlugin: ICC profile data out of bounds");
return ReadonlyBytes { m_context->file_bytes + header_size + v5.profile_data, v5.profile_size };

View file

@ -99,6 +99,14 @@ TEST_CASE(test_bmp_negative_int_min_height)
EXPECT(plugin_decoder->frame(0).is_error());
}
TEST_CASE(test_bmp_v5_icc_profile_out_of_bounds)
{
auto file = TRY_OR_FAIL(Core::MappedFile::map(TEST_INPUT("bmp/v5-icc-profile-out-of-bounds.bmp"sv)));
EXPECT(Gfx::BMPImageDecoderPlugin::sniff(file->bytes()));
auto plugin_decoder = TRY_OR_FAIL(Gfx::BMPImageDecoderPlugin::create(file->bytes()));
EXPECT(plugin_decoder->icc_data().is_error());
}
TEST_CASE(test_bmp_os2_3bit)
{
auto file = TRY_OR_FAIL(Core::MappedFile::map(TEST_INPUT("bmp/os2_3bpc.bmp"sv)));

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 B