mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 11:37:34 +00:00
LibGfx+Fuzz: Convert ImageDecoder::initialize to ErrorOr
This prevents callers from accidentally discarding the result of initialize(), which was the root cause of this OSS Fuzz bug: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=55896&q=label%3AProj-serenity&sort=summary
This commit is contained in:
parent
a84e64ed22
commit
da394abe04
37 changed files with 125 additions and 105 deletions
|
@ -1501,9 +1501,9 @@ bool BMPImageDecoderPlugin::set_nonvolatile(bool& was_purged)
|
|||
return m_context->bitmap->set_nonvolatile(was_purged);
|
||||
}
|
||||
|
||||
bool BMPImageDecoderPlugin::initialize()
|
||||
ErrorOr<void> BMPImageDecoderPlugin::initialize()
|
||||
{
|
||||
return !decode_bmp_header(*m_context).is_error();
|
||||
return decode_bmp_header(*m_context);
|
||||
}
|
||||
|
||||
bool BMPImageDecoderPlugin::sniff(ReadonlyBytes data)
|
||||
|
|
|
@ -30,7 +30,7 @@ public:
|
|||
virtual IntSize size() override;
|
||||
virtual void set_volatile() override;
|
||||
[[nodiscard]] virtual bool set_nonvolatile(bool& was_purged) override;
|
||||
virtual bool initialize() override;
|
||||
virtual ErrorOr<void> initialize() override;
|
||||
bool sniff_dib();
|
||||
virtual bool is_animated() override;
|
||||
virtual size_t loop_count() override;
|
||||
|
|
|
@ -645,14 +645,17 @@ bool DDSImageDecoderPlugin::set_nonvolatile(bool& was_purged)
|
|||
return m_context->bitmap->set_nonvolatile(was_purged);
|
||||
}
|
||||
|
||||
bool DDSImageDecoderPlugin::initialize()
|
||||
ErrorOr<void> DDSImageDecoderPlugin::initialize()
|
||||
{
|
||||
// The header is always at least 128 bytes, so if the file is smaller, it can't be a DDS.
|
||||
return m_context->data_size > 128
|
||||
if (m_context->data_size > 128
|
||||
&& m_context->data[0] == 0x44
|
||||
&& m_context->data[1] == 0x44
|
||||
&& m_context->data[2] == 0x53
|
||||
&& m_context->data[3] == 0x20;
|
||||
&& m_context->data[3] == 0x20)
|
||||
return {};
|
||||
|
||||
return Error::from_string_literal("Bad image magic");
|
||||
}
|
||||
|
||||
bool DDSImageDecoderPlugin::sniff(ReadonlyBytes data)
|
||||
|
|
|
@ -243,7 +243,7 @@ public:
|
|||
virtual IntSize size() override;
|
||||
virtual void set_volatile() override;
|
||||
[[nodiscard]] virtual bool set_nonvolatile(bool& was_purged) override;
|
||||
virtual bool initialize() override;
|
||||
virtual ErrorOr<void> initialize() override;
|
||||
virtual bool is_animated() override;
|
||||
virtual size_t loop_count() override;
|
||||
virtual size_t frame_count() override;
|
||||
|
|
|
@ -562,10 +562,11 @@ bool GIFImageDecoderPlugin::set_nonvolatile(bool& was_purged)
|
|||
return m_context->frame_buffer->set_nonvolatile(was_purged);
|
||||
}
|
||||
|
||||
bool GIFImageDecoderPlugin::initialize()
|
||||
ErrorOr<void> GIFImageDecoderPlugin::initialize()
|
||||
{
|
||||
FixedMemoryStream stream { { m_context->data, m_context->data_size } };
|
||||
return !decode_gif_header(stream).is_error();
|
||||
TRY(decode_gif_header(stream));
|
||||
return {};
|
||||
}
|
||||
|
||||
bool GIFImageDecoderPlugin::sniff(ReadonlyBytes data)
|
||||
|
|
|
@ -23,7 +23,7 @@ public:
|
|||
virtual IntSize size() override;
|
||||
virtual void set_volatile() override;
|
||||
[[nodiscard]] virtual bool set_nonvolatile(bool& was_purged) override;
|
||||
virtual bool initialize() override;
|
||||
virtual ErrorOr<void> initialize() override;
|
||||
virtual bool is_animated() override;
|
||||
virtual size_t loop_count() override;
|
||||
virtual size_t frame_count() override;
|
||||
|
|
|
@ -150,16 +150,14 @@ ErrorOr<void> ICOImageDecoderPlugin::load_ico_bitmap(ICOLoadingContext& context,
|
|||
ICOImageDescriptor& desc = context.images[real_index];
|
||||
if (PNGImageDecoderPlugin::sniff({ context.data + desc.offset, desc.size })) {
|
||||
auto png_decoder = TRY(PNGImageDecoderPlugin::create({ context.data + desc.offset, desc.size }));
|
||||
if (png_decoder->initialize()) {
|
||||
auto decoded_png_frame = TRY(png_decoder->frame(0));
|
||||
if (!decoded_png_frame.image) {
|
||||
dbgln_if(ICO_DEBUG, "load_ico_bitmap: failed to load PNG encoded image index: {}", real_index);
|
||||
return Error::from_string_literal("Encoded image not null");
|
||||
}
|
||||
desc.bitmap = decoded_png_frame.image;
|
||||
return {};
|
||||
TRY(png_decoder->initialize());
|
||||
auto decoded_png_frame = TRY(png_decoder->frame(0));
|
||||
if (!decoded_png_frame.image) {
|
||||
dbgln_if(ICO_DEBUG, "load_ico_bitmap: failed to load PNG encoded image index: {}", real_index);
|
||||
return Error::from_string_literal("Encoded image not null");
|
||||
}
|
||||
return Error::from_string_literal("Couldn't initialize PNG Decoder");
|
||||
desc.bitmap = decoded_png_frame.image;
|
||||
return {};
|
||||
} else {
|
||||
auto bmp_decoder = TRY(BMPImageDecoderPlugin::create_as_included_in_ico({}, { context.data + desc.offset, desc.size }));
|
||||
// NOTE: We don't initialize a BMP decoder in the usual way, but rather
|
||||
|
@ -230,10 +228,11 @@ bool ICOImageDecoderPlugin::set_nonvolatile(bool& was_purged)
|
|||
return m_context->images[0].bitmap->set_nonvolatile(was_purged);
|
||||
}
|
||||
|
||||
bool ICOImageDecoderPlugin::initialize()
|
||||
ErrorOr<void> ICOImageDecoderPlugin::initialize()
|
||||
{
|
||||
FixedMemoryStream stream { { m_context->data, m_context->data_size } };
|
||||
return !decode_ico_header(stream).is_error();
|
||||
TRY(decode_ico_header(stream));
|
||||
return {};
|
||||
}
|
||||
|
||||
bool ICOImageDecoderPlugin::is_animated()
|
||||
|
|
|
@ -22,7 +22,7 @@ public:
|
|||
virtual IntSize size() override;
|
||||
virtual void set_volatile() override;
|
||||
[[nodiscard]] virtual bool set_nonvolatile(bool& was_purged) override;
|
||||
virtual bool initialize() override;
|
||||
virtual ErrorOr<void> initialize() override;
|
||||
virtual bool is_animated() override;
|
||||
virtual size_t loop_count() override;
|
||||
virtual size_t frame_count() override;
|
||||
|
|
|
@ -47,7 +47,7 @@ static OwnPtr<ImageDecoderPlugin> probe_and_sniff_for_appropriate_plugin(Readonl
|
|||
if (!sniff_result)
|
||||
continue;
|
||||
auto plugin_decoder = plugin.create(bytes).release_value_but_fixme_should_propagate_errors();
|
||||
if (plugin_decoder->initialize())
|
||||
if (!plugin_decoder->initialize().is_error())
|
||||
return plugin_decoder;
|
||||
}
|
||||
return {};
|
||||
|
@ -72,7 +72,7 @@ static OwnPtr<ImageDecoderPlugin> probe_and_sniff_for_appropriate_plugin_with_kn
|
|||
if (!validation_result)
|
||||
continue;
|
||||
auto plugin_decoder = plugin.create(bytes).release_value_but_fixme_should_propagate_errors();
|
||||
if (plugin_decoder->initialize())
|
||||
if (!plugin_decoder->initialize().is_error())
|
||||
return plugin_decoder;
|
||||
}
|
||||
return {};
|
||||
|
|
|
@ -34,7 +34,7 @@ public:
|
|||
virtual void set_volatile() = 0;
|
||||
[[nodiscard]] virtual bool set_nonvolatile(bool& was_purged) = 0;
|
||||
|
||||
virtual bool initialize() = 0;
|
||||
virtual ErrorOr<void> initialize() = 0;
|
||||
|
||||
virtual bool is_animated() = 0;
|
||||
virtual size_t loop_count() = 0;
|
||||
|
|
|
@ -1887,9 +1887,9 @@ bool JPEGImageDecoderPlugin::set_nonvolatile(bool& was_purged)
|
|||
return m_context->bitmap->set_nonvolatile(was_purged);
|
||||
}
|
||||
|
||||
bool JPEGImageDecoderPlugin::initialize()
|
||||
ErrorOr<void> JPEGImageDecoderPlugin::initialize()
|
||||
{
|
||||
return true;
|
||||
return {};
|
||||
}
|
||||
|
||||
bool JPEGImageDecoderPlugin::sniff(ReadonlyBytes data)
|
||||
|
|
|
@ -25,7 +25,7 @@ public:
|
|||
virtual IntSize size() override;
|
||||
virtual void set_volatile() override;
|
||||
[[nodiscard]] virtual bool set_nonvolatile(bool& was_purged) override;
|
||||
virtual bool initialize() override;
|
||||
virtual ErrorOr<void> initialize() override;
|
||||
virtual bool is_animated() override;
|
||||
virtual size_t loop_count() override;
|
||||
virtual size_t frame_count() override;
|
||||
|
|
|
@ -1322,9 +1322,11 @@ bool PNGImageDecoderPlugin::set_nonvolatile(bool& was_purged)
|
|||
return m_context->bitmap->set_nonvolatile(was_purged);
|
||||
}
|
||||
|
||||
bool PNGImageDecoderPlugin::initialize()
|
||||
ErrorOr<void> PNGImageDecoderPlugin::initialize()
|
||||
{
|
||||
return decode_png_header(*m_context);
|
||||
if (decode_png_header(*m_context))
|
||||
return {};
|
||||
return Error::from_string_literal("bad image header");
|
||||
}
|
||||
|
||||
bool PNGImageDecoderPlugin::sniff(ReadonlyBytes data)
|
||||
|
|
|
@ -22,7 +22,7 @@ public:
|
|||
virtual IntSize size() override;
|
||||
virtual void set_volatile() override;
|
||||
[[nodiscard]] virtual bool set_nonvolatile(bool& was_purged) override;
|
||||
virtual bool initialize() override;
|
||||
virtual ErrorOr<void> initialize() override;
|
||||
virtual bool is_animated() override;
|
||||
virtual size_t loop_count() override;
|
||||
virtual size_t frame_count() override;
|
||||
|
|
|
@ -67,7 +67,7 @@ public:
|
|||
virtual void set_volatile() override;
|
||||
[[nodiscard]] virtual bool set_nonvolatile(bool& was_purged) override;
|
||||
|
||||
virtual bool initialize() override { return true; }
|
||||
virtual ErrorOr<void> initialize() override { return {}; }
|
||||
virtual bool is_animated() override;
|
||||
virtual size_t loop_count() override;
|
||||
virtual size_t frame_count() override;
|
||||
|
|
|
@ -195,9 +195,9 @@ bool QOIImageDecoderPlugin::set_nonvolatile(bool& was_purged)
|
|||
return m_context->bitmap->set_nonvolatile(was_purged);
|
||||
}
|
||||
|
||||
bool QOIImageDecoderPlugin::initialize()
|
||||
ErrorOr<void> QOIImageDecoderPlugin::initialize()
|
||||
{
|
||||
return !decode_header_and_update_context(*m_context->stream).is_error();
|
||||
return decode_header_and_update_context(*m_context->stream);
|
||||
}
|
||||
|
||||
bool QOIImageDecoderPlugin::sniff(ReadonlyBytes data)
|
||||
|
|
|
@ -46,7 +46,7 @@ public:
|
|||
virtual IntSize size() override;
|
||||
virtual void set_volatile() override;
|
||||
[[nodiscard]] virtual bool set_nonvolatile(bool& was_purged) override;
|
||||
virtual bool initialize() override;
|
||||
virtual ErrorOr<void> initialize() override;
|
||||
virtual bool is_animated() override { return false; }
|
||||
virtual size_t loop_count() override { return 0; }
|
||||
virtual size_t frame_count() override { return 1; }
|
||||
|
|
|
@ -219,9 +219,11 @@ bool TGAImageDecoderPlugin::decode_tga_header()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool TGAImageDecoderPlugin::initialize()
|
||||
ErrorOr<void> TGAImageDecoderPlugin::initialize()
|
||||
{
|
||||
return decode_tga_header();
|
||||
if (decode_tga_header())
|
||||
return {};
|
||||
return Error::from_string_literal("Bad TGA header");
|
||||
}
|
||||
|
||||
ErrorOr<bool> TGAImageDecoderPlugin::validate_before_create(ReadonlyBytes data)
|
||||
|
|
|
@ -23,7 +23,7 @@ public:
|
|||
virtual IntSize size() override;
|
||||
virtual void set_volatile() override;
|
||||
[[nodiscard]] virtual bool set_nonvolatile(bool& was_purged) override;
|
||||
virtual bool initialize() override;
|
||||
virtual ErrorOr<void> initialize() override;
|
||||
virtual bool is_animated() override;
|
||||
virtual size_t loop_count() override;
|
||||
virtual size_t frame_count() override;
|
||||
|
|
|
@ -629,7 +629,7 @@ WebPImageDecoderPlugin::WebPImageDecoderPlugin(ReadonlyBytes data, OwnPtr<WebPLo
|
|||
|
||||
WebPImageDecoderPlugin::~WebPImageDecoderPlugin() = default;
|
||||
|
||||
bool WebPImageDecoderPlugin::set_error(ErrorOr<void>&& error_or)
|
||||
bool WebPImageDecoderPlugin::set_error(ErrorOr<void> const& error_or)
|
||||
{
|
||||
if (error_or.is_error()) {
|
||||
m_context->state = WebPLoadingContext::State::Error;
|
||||
|
@ -664,9 +664,11 @@ bool WebPImageDecoderPlugin::set_nonvolatile(bool& was_purged)
|
|||
return m_context->bitmap->set_nonvolatile(was_purged);
|
||||
}
|
||||
|
||||
bool WebPImageDecoderPlugin::initialize()
|
||||
ErrorOr<void> WebPImageDecoderPlugin::initialize()
|
||||
{
|
||||
return !set_error(decode_webp_header(*m_context));
|
||||
auto header_okay_or_error = decode_webp_header(*m_context);
|
||||
set_error(header_okay_or_error);
|
||||
return header_okay_or_error;
|
||||
}
|
||||
|
||||
bool WebPImageDecoderPlugin::sniff(ReadonlyBytes data)
|
||||
|
|
|
@ -22,7 +22,7 @@ public:
|
|||
virtual IntSize size() override;
|
||||
virtual void set_volatile() override;
|
||||
[[nodiscard]] virtual bool set_nonvolatile(bool& was_purged) override;
|
||||
virtual bool initialize() override;
|
||||
virtual ErrorOr<void> initialize() override;
|
||||
virtual bool is_animated() override;
|
||||
virtual size_t loop_count() override;
|
||||
virtual size_t frame_count() override;
|
||||
|
@ -31,7 +31,7 @@ public:
|
|||
virtual ErrorOr<Optional<ReadonlyBytes>> icc_data() override;
|
||||
|
||||
private:
|
||||
bool set_error(ErrorOr<void>&&);
|
||||
bool set_error(ErrorOr<void> const&);
|
||||
|
||||
WebPImageDecoderPlugin(ReadonlyBytes, OwnPtr<WebPLoadingContext>);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue