LibGfx: Reject the Invalid bitmap format from IPC decoders

Problem: A borked process sending a Gfx::Bitmap (inside BitmapSequence)
or a Gfx::ShareableBitmap over IPC could set BitmapFormat::Invalid as
the format field. The receiving process then aborted while decoding the
message — an IPC-reachable crash.

Cause: The helper that both decoders use for validating the format read
off the wire accepts BitmapFormat::Invalid. The decoders go on to build
a bitmap with that format. But that triggers an assert — because
minimum_pitch only knows the four real pixel formats.

Fix: Drop BitmapFormat::Invalid from is_valid_bitmap_format. It’s an
indicator of an absent/unknown format, never one a real bitmap can have.
And any real bitmap is never encoded with it. So, both BitmapSequence
and ShareableBitmap decode now return a clean decode error for it.
This commit is contained in:
sideshowbarker 2026-06-19 15:23:57 +09:00 committed by Andreas Kling
parent fdca036ff3
commit 9d64cd8c9b
3 changed files with 57 additions and 1 deletions

View file

@ -38,7 +38,6 @@ enum class BitmapFormat {
inline bool is_valid_bitmap_format(u32 const format)
{
switch (format) {
case static_cast<u32>(BitmapFormat::Invalid):
case static_cast<u32>(BitmapFormat::BGRx8888):
case static_cast<u32>(BitmapFormat::RGBx8888):
case static_cast<u32>(BitmapFormat::BGRA8888):

View file

@ -18,4 +18,5 @@ target_link_libraries(BenchmarkJPEGLoader PRIVATE LibImageDecoders)
target_link_libraries(TestImageDecoder PRIVATE LibImageDecoders)
target_link_libraries(TestImageWriter PRIVATE LibImageDecoders)
ladybird_test(TestShareableBitmap.cpp LibGfx LIBS LibGfx LibIPC)
ladybird_test(TestYUVData.cpp LibGfx LIBS LibGfx skia)

View file

@ -0,0 +1,56 @@
/*
* Copyright (c) 2026, Ladybird contributors
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/MemoryStream.h>
#include <AK/Queue.h>
#include <LibCore/AnonymousBuffer.h>
#include <LibGfx/Bitmap.h>
#include <LibGfx/ShareableBitmap.h>
#include <LibGfx/Size.h>
#include <LibIPC/Attachment.h>
#include <LibIPC/Decoder.h>
#include <LibIPC/Encoder.h>
#include <LibIPC/File.h>
#include <LibIPC/Message.h>
#include <LibTest/TestCase.h>
static ErrorOr<Gfx::ShareableBitmap> decode_shareable_bitmap(Gfx::BitmapFormat format, Gfx::IntSize size, size_t buffer_size)
{
auto buffer = MUST(Core::AnonymousBuffer::create_with_size(buffer_size));
IPC::MessageBuffer message_buffer;
IPC::Encoder encoder { message_buffer };
MUST(encoder.encode(true));
MUST(encoder.encode(MUST(IPC::File::clone_fd(buffer.fd()))));
MUST(encoder.encode(size));
MUST(encoder.encode(static_cast<u32>(format)));
MUST(encoder.encode(static_cast<u32>(Gfx::AlphaType::Premultiplied)));
auto data = message_buffer.take_data();
FixedMemoryStream stream { data.span() };
Queue<IPC::Attachment> attachments;
for (auto& attachment : message_buffer.take_attachments())
attachments.enqueue(move(attachment));
IPC::Decoder decoder { stream, attachments };
return IPC::decode<Gfx::ShareableBitmap>(decoder);
}
TEST_CASE(decode_rejects_invalid_bitmap_format)
{
// A ShareableBitmap whose format field is BitmapFormat::Invalid must be rejected at the IPC boundary. Accepting it
// previously reached minimum_pitch(), which has no case for Invalid and trips an assert — an IPC-reachable crash.
auto result = decode_shareable_bitmap(Gfx::BitmapFormat::Invalid, Gfx::IntSize { 16, 16 }, 1024);
EXPECT(result.is_error());
}
TEST_CASE(decode_accepts_valid_bitmap_format)
{
auto required = Gfx::Bitmap::size_in_bytes(Gfx::Bitmap::minimum_pitch(16, Gfx::BitmapFormat::BGRA8888), 16);
auto result = decode_shareable_bitmap(Gfx::BitmapFormat::BGRA8888, Gfx::IntSize { 16, 16 }, required);
EXPECT(!result.is_error());
}