LibGfx: Fix heap overflow applying Exif transpose to non-square images
Problem: Decoding a non-square image whose Exif orientation is 5 (transpose) writes one pixel past the end of the destination bitmap — an ASan heap-buffer-overflow in ExifOrientedBitmap::set_pixel. Cause: oriented_position() mapped orientation 5 by composing the “flip-horizontally” and “rotate-90-clockwise” helpers. Each helper mirrors using the source width. But after the rotate, the point is already in the transposed coordinate space — where the relevant dimension is the source height. For a non-square image, that composition produces x-coordinates past the destination width. Only square images happened to stay in bounds. The destination bitmap is the transposed size — so the out-of-range column wrote past its allocation. Fix: Map orientation 5 directly as a transpose across the main diagonal: source (x, y) to destination (y, x). Fixes https://github.com/LadybirdBrowser/ladybird/issues/10102
This commit is contained in:
parent
69654a3a7c
commit
20b1129352
3 changed files with 17 additions and 1 deletions
|
|
@ -92,7 +92,7 @@ private:
|
|||
case Orientation::FlipVertically:
|
||||
return IntPoint(point.x(), m_height - point.y() - 1);
|
||||
case Orientation::Rotate90ClockwiseThenFlipHorizontally:
|
||||
return flip_horizontally(rotate_90_clockwise(point));
|
||||
return IntPoint(point.y(), point.x());
|
||||
case Orientation::Rotate90Clockwise:
|
||||
return rotate_90_clockwise(point);
|
||||
case Orientation::FlipHorizontallyThenRotate90Clockwise:
|
||||
|
|
|
|||
|
|
@ -546,6 +546,22 @@ TEST_CASE(test_exif)
|
|||
EXPECT_EQ(frame.image->get_pixel(190, 10), Gfx::Color(255, 0, 0));
|
||||
}
|
||||
|
||||
TEST_CASE(test_exif_orientation_transpose_non_square)
|
||||
{
|
||||
auto file = TRY_OR_FAIL(Core::MappedFile::map(TEST_INPUT("png/exif-orientation-5.png"sv)));
|
||||
EXPECT(Gfx::PNGImageDecoderPlugin::sniff(file->bytes()));
|
||||
auto plugin_decoder = TRY_OR_FAIL(Gfx::PNGImageDecoderPlugin::create(file->bytes()));
|
||||
|
||||
auto frame = TRY_OR_FAIL(expect_single_frame_of_size(*plugin_decoder, { 1, 3 }));
|
||||
EXPECT(plugin_decoder->metadata().has_value());
|
||||
auto const& exif_metadata = static_cast<Gfx::ExifMetadata const&>(plugin_decoder->metadata().value());
|
||||
EXPECT_EQ(*exif_metadata.orientation(), Gfx::TIFF::Orientation::Rotate90ClockwiseThenFlipHorizontally);
|
||||
|
||||
EXPECT_EQ(frame.image->get_pixel(0, 0), Gfx::Color(255, 0, 0));
|
||||
EXPECT_EQ(frame.image->get_pixel(0, 1), Gfx::Color(0, 255, 0));
|
||||
EXPECT_EQ(frame.image->get_pixel(0, 2), Gfx::Color(0, 0, 255));
|
||||
}
|
||||
|
||||
TEST_CASE(test_png_malformed_frame)
|
||||
{
|
||||
Array test_inputs = {
|
||||
|
|
|
|||
BIN
Tests/LibGfx/test-inputs/png/exif-orientation-5.png
Normal file
BIN
Tests/LibGfx/test-inputs/png/exif-orientation-5.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 109 B |
Loading…
Reference in a new issue