diff options
author | Liav A <liavalb@gmail.com> | 2023-01-20 18:50:49 +0200 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2023-01-20 17:05:09 +0000 |
commit | 5b273f3823ece7b0eb4a4a5bf6711bf92a9e3d2d (patch) | |
tree | 9e56cb6b4898f8135561c0038361ffbe578df8bf | |
parent | 20033d06d8c1276ee4caab72f42aaee14ca256af (diff) | |
download | serenity-5b273f3823ece7b0eb4a4a5bf6711bf92a9e3d2d.zip |
LibGfx: Fix TGA decoder being out of boundary after calling frame method
This happened because the reader was incrementing the byte index of it
after each read of a byte from the Span, so by the end of the frame
method, we could be at the end of the mapped file, so the next call
on the same decoder will just resume from that point and will be quickly
out of boundary.
To ensure this doesn't happen we only set the bitmap to m_context member
at the end of the method, and call to that method again will just give
the already-generated bitmap.
In case of setting the bitmap as volatile, we test for that case and
re-generate a reader to read the frame again correctly.
-rw-r--r-- | Userland/Libraries/LibGfx/TGALoader.cpp | 28 |
1 files changed, 23 insertions, 5 deletions
diff --git a/Userland/Libraries/LibGfx/TGALoader.cpp b/Userland/Libraries/LibGfx/TGALoader.cpp index b699194449..e8ee56445c 100644 --- a/Userland/Libraries/LibGfx/TGALoader.cpp +++ b/Userland/Libraries/LibGfx/TGALoader.cpp @@ -65,6 +65,12 @@ public: { } + TGAReader(ReadonlyBytes data, size_t index) + : m_data(move(data)) + , m_index(index) + { + } + ALWAYS_INLINE u8 read_u8() { u8 value = m_data[m_index]; @@ -265,13 +271,25 @@ ErrorOr<ImageFrameDescriptor> TGAImageDecoderPlugin::frame(size_t index) if (color_map > 1) return Error::from_string_literal("TGAImageDecoderPlugin: Invalid color map type"); + if (m_context->bitmap) { + return ImageFrameDescriptor { m_context->bitmap, 0 }; + } else { + // NOTE: Just to be on the safe side, if m_context->bitmap is nullptr, then + // just re-construct the reader object. This will ensure that if the bitmap + // was set as volatile and therefore it is gone, we can always re-generate it + // with a new call to this method! + VERIFY(m_context->reader); + m_context->reader = make<TGAReader>(m_context->reader->data(), sizeof(TGAHeader)); + } + + RefPtr<Gfx::Bitmap> bitmap; switch (bits_per_pixel) { case 24: - m_context->bitmap = TRY(Bitmap::try_create(BitmapFormat::BGRx8888, { m_context->header.width, m_context->header.height })); + bitmap = TRY(Bitmap::try_create(BitmapFormat::BGRx8888, { m_context->header.width, m_context->header.height })); break; case 32: - m_context->bitmap = TRY(Bitmap::try_create(BitmapFormat::BGRA8888, { m_context->header.width, m_context->header.height })); + bitmap = TRY(Bitmap::try_create(BitmapFormat::BGRA8888, { m_context->header.width, m_context->header.height })); break; default: @@ -303,7 +321,7 @@ ErrorOr<ImageFrameDescriptor> TGAImageDecoderPlugin::frame(size_t index) auto actual_col = col; if (x_origin > width) actual_col = width - 1 - col; - m_context->bitmap->scanline(actual_row)[actual_col] = pixel.data; + bitmap->scanline(actual_row)[actual_col] = pixel.data; } } break; @@ -325,7 +343,7 @@ ErrorOr<ImageFrameDescriptor> TGAImageDecoderPlugin::frame(size_t index) auto actual_col = col; if (x_origin > width) actual_col = width - 1 - col; - m_context->bitmap->scanline(actual_row)[actual_col] = pixel.data; + bitmap->scanline(actual_row)[actual_col] = pixel.data; if (packet_type.raw && (current_pixel_index + 1) < max_pixel_index) pixel = m_context->reader->read_pixel(bits_per_pixel); } @@ -338,7 +356,7 @@ ErrorOr<ImageFrameDescriptor> TGAImageDecoderPlugin::frame(size_t index) return Error::from_string_literal("TGAImageDecoderPlugin: Can currently only handle the UncompressedRGB or CompressedRGB data type"); } - VERIFY(m_context->bitmap); + m_context->bitmap = bitmap; return ImageFrameDescriptor { m_context->bitmap, 0 }; } } |