LibGfx: Avoid undefined behavior on a BMP with an INT_MIN height
Problem: Decoding a BMP whose height is INT_MIN triggered a UBSan error. A top-down BMP legitimately uses a negative height — and unlike width, it’s not rejected, so it can be INT_MIN. Cause: decode_bmp_pixel_data() took the magnitude of the i32 width and height with abs(). Negating INT_MIN is undefined behavior. Fix: Widen to i64 before taking the absolute value — so the magnitude of INT_MIN is representable. The resulting out-of-range dimension is still rejected by Bitmap::create — so only the undefined behavior changes. Fixes: https://github.com/LadybirdBrowser/ladybird/issues/9994
This commit is contained in:
parent
20b1129352
commit
9bde8a5c88
3 changed files with 10 additions and 2 deletions
|
|
@ -1297,8 +1297,9 @@ static ErrorOr<void> decode_bmp_pixel_data(BMPLoadingContext& context)
|
|||
return Error::from_string_literal("BMP has invalid bpp");
|
||||
}
|
||||
|
||||
u32 const width = abs(context.dib.core.width);
|
||||
u32 const height = !context.is_included_in_ico ? abs(context.dib.core.height) : (abs(context.dib.core.height) / 2);
|
||||
u32 const width = static_cast<u32>(abs(static_cast<i64>(context.dib.core.width)));
|
||||
u32 const absolute_height = static_cast<u32>(abs(static_cast<i64>(context.dib.core.height)));
|
||||
u32 const height = !context.is_included_in_ico ? absolute_height : (absolute_height / 2);
|
||||
|
||||
context.bitmap = TRY(Bitmap::create(format, Gfx::AlphaType::Unpremultiplied, { static_cast<int>(width), static_cast<int>(height) }));
|
||||
|
||||
|
|
|
|||
|
|
@ -92,6 +92,13 @@ TEST_CASE(test_bmp_v4)
|
|||
EXPECT_EQ(frame.image->get_pixel(0, 0), Gfx::Color::NamedColor::Red);
|
||||
}
|
||||
|
||||
TEST_CASE(test_bmp_negative_int_min_height)
|
||||
{
|
||||
auto file = TRY_OR_FAIL(Core::MappedFile::map(TEST_INPUT("bmp/negative-height-int-min.bmp"sv)));
|
||||
auto plugin_decoder = TRY_OR_FAIL(Gfx::BMPImageDecoderPlugin::create(file->bytes()));
|
||||
EXPECT(plugin_decoder->frame(0).is_error());
|
||||
}
|
||||
|
||||
TEST_CASE(test_bmp_os2_3bit)
|
||||
{
|
||||
auto file = TRY_OR_FAIL(Core::MappedFile::map(TEST_INPUT("bmp/os2_3bpc.bmp"sv)));
|
||||
|
|
|
|||
BIN
Tests/LibGfx/test-inputs/bmp/negative-height-int-min.bmp
Normal file
BIN
Tests/LibGfx/test-inputs/bmp/negative-height-int-min.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 58 B |
Loading…
Reference in a new issue