Browse Source

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
Ben Wiederhake 2 năm trước cách đây
mục cha
commit
da394abe04
37 tập tin đã thay đổi với 125 bổ sung105 xóa
  1. 3 2
      Meta/Lagom/Fuzzers/FuzzBMPLoader.cpp
  2. 3 1
      Meta/Lagom/Fuzzers/FuzzGIFLoader.cpp
  3. 3 2
      Meta/Lagom/Fuzzers/FuzzICOLoader.cpp
  4. 3 2
      Meta/Lagom/Fuzzers/FuzzJPEGLoader.cpp
  5. 3 2
      Meta/Lagom/Fuzzers/FuzzPBMLoader.cpp
  6. 3 2
      Meta/Lagom/Fuzzers/FuzzPGMLoader.cpp
  7. 3 2
      Meta/Lagom/Fuzzers/FuzzPNGLoader.cpp
  8. 3 2
      Meta/Lagom/Fuzzers/FuzzPPMLoader.cpp
  9. 3 2
      Meta/Lagom/Fuzzers/FuzzQOILoader.cpp
  10. 3 2
      Meta/Lagom/Fuzzers/FuzzTGALoader.cpp
  11. 3 2
      Meta/Lagom/Fuzzers/FuzzWebPLoader.cpp
  12. 4 4
      Tests/LibGfx/TestICCProfile.cpp
  13. 29 29
      Tests/LibGfx/TestImageDecoder.cpp
  14. 1 1
      Userland/Libraries/LibGUI/FileIconProvider.cpp
  15. 2 2
      Userland/Libraries/LibGfx/ImageFormats/BMPLoader.cpp
  16. 1 1
      Userland/Libraries/LibGfx/ImageFormats/BMPLoader.h
  17. 6 3
      Userland/Libraries/LibGfx/ImageFormats/DDSLoader.cpp
  18. 1 1
      Userland/Libraries/LibGfx/ImageFormats/DDSLoader.h
  19. 3 2
      Userland/Libraries/LibGfx/ImageFormats/GIFLoader.cpp
  20. 1 1
      Userland/Libraries/LibGfx/ImageFormats/GIFLoader.h
  21. 10 11
      Userland/Libraries/LibGfx/ImageFormats/ICOLoader.cpp
  22. 1 1
      Userland/Libraries/LibGfx/ImageFormats/ICOLoader.h
  23. 2 2
      Userland/Libraries/LibGfx/ImageFormats/ImageDecoder.cpp
  24. 1 1
      Userland/Libraries/LibGfx/ImageFormats/ImageDecoder.h
  25. 2 2
      Userland/Libraries/LibGfx/ImageFormats/JPEGLoader.cpp
  26. 1 1
      Userland/Libraries/LibGfx/ImageFormats/JPEGLoader.h
  27. 4 2
      Userland/Libraries/LibGfx/ImageFormats/PNGLoader.cpp
  28. 1 1
      Userland/Libraries/LibGfx/ImageFormats/PNGLoader.h
  29. 1 1
      Userland/Libraries/LibGfx/ImageFormats/PortableImageMapLoader.h
  30. 2 2
      Userland/Libraries/LibGfx/ImageFormats/QOILoader.cpp
  31. 1 1
      Userland/Libraries/LibGfx/ImageFormats/QOILoader.h
  32. 4 2
      Userland/Libraries/LibGfx/ImageFormats/TGALoader.cpp
  33. 1 1
      Userland/Libraries/LibGfx/ImageFormats/TGALoader.h
  34. 5 3
      Userland/Libraries/LibGfx/ImageFormats/WebPLoader.cpp
  35. 2 2
      Userland/Libraries/LibGfx/ImageFormats/WebPLoader.h
  36. 3 4
      Userland/Libraries/LibPDF/Filter.cpp
  37. 3 3
      Userland/Services/SpiceAgent/SpiceAgent.cpp

+ 3 - 2
Meta/Lagom/Fuzzers/FuzzBMPLoader.cpp

@@ -13,7 +13,8 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* data, size_t size)
     if (decoder_or_error.is_error())
         return 0;
     auto decoder = decoder_or_error.release_value();
-    decoder->initialize();
-    (void)decoder->frame(0);
+    if (!decoder->initialize().is_error()) {
+        (void)decoder->frame(0);
+    }
     return 0;
 }

+ 3 - 1
Meta/Lagom/Fuzzers/FuzzGIFLoader.cpp

@@ -16,7 +16,9 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* data, size_t size)
     if (decoder_or_error.is_error())
         return 0;
     auto decoder = decoder_or_error.release_value();
-    decoder->initialize();
+    if (decoder->initialize().is_error()) {
+        return 0;
+    }
     auto& gif_decoder = *decoder;
     auto bitmap_or_error = decoder->frame(0);
     if (!bitmap_or_error.is_error()) {

+ 3 - 2
Meta/Lagom/Fuzzers/FuzzICOLoader.cpp

@@ -14,7 +14,8 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* data, size_t size)
     if (decoder_or_error.is_error())
         return 0;
     auto decoder = decoder_or_error.release_value();
-    decoder->initialize();
-    (void)decoder->frame(0);
+    if (!decoder->initialize().is_error()) {
+        (void)decoder->frame(0);
+    }
     return 0;
 }

+ 3 - 2
Meta/Lagom/Fuzzers/FuzzJPEGLoader.cpp

@@ -14,7 +14,8 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* data, size_t size)
     if (decoder_or_error.is_error())
         return 0;
     auto decoder = decoder_or_error.release_value();
-    decoder->initialize();
-    (void)decoder->frame(0);
+    if (!decoder->initialize().is_error()) {
+        (void)decoder->frame(0);
+    }
     return 0;
 }

+ 3 - 2
Meta/Lagom/Fuzzers/FuzzPBMLoader.cpp

@@ -14,7 +14,8 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* data, size_t size)
     if (decoder_or_error.is_error())
         return 0;
     auto decoder = decoder_or_error.release_value();
-    decoder->initialize();
-    (void)decoder->frame(0);
+    if (!decoder->initialize().is_error()) {
+        (void)decoder->frame(0);
+    }
     return 0;
 }

+ 3 - 2
Meta/Lagom/Fuzzers/FuzzPGMLoader.cpp

@@ -14,7 +14,8 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* data, size_t size)
     if (decoder_or_error.is_error())
         return 0;
     auto decoder = decoder_or_error.release_value();
-    decoder->initialize();
-    (void)decoder->frame(0);
+    if (!decoder->initialize().is_error()) {
+        (void)decoder->frame(0);
+    }
     return 0;
 }

+ 3 - 2
Meta/Lagom/Fuzzers/FuzzPNGLoader.cpp

@@ -14,7 +14,8 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* data, size_t size)
     if (decoder_or_error.is_error())
         return 0;
     auto decoder = decoder_or_error.release_value();
-    decoder->initialize();
-    (void)decoder->frame(0);
+    if (!decoder->initialize().is_error()) {
+        (void)decoder->frame(0);
+    }
     return 0;
 }

+ 3 - 2
Meta/Lagom/Fuzzers/FuzzPPMLoader.cpp

@@ -14,7 +14,8 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* data, size_t size)
     if (decoder_or_error.is_error())
         return 0;
     auto decoder = decoder_or_error.release_value();
-    decoder->initialize();
-    (void)decoder->frame(0);
+    if (!decoder->initialize().is_error()) {
+        (void)decoder->frame(0);
+    }
     return 0;
 }

+ 3 - 2
Meta/Lagom/Fuzzers/FuzzQOILoader.cpp

@@ -14,7 +14,8 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* data, size_t size)
     if (decoder_or_error.is_error())
         return 0;
     auto decoder = decoder_or_error.release_value();
-    decoder->initialize();
-    (void)decoder->frame(0);
+    if (!decoder->initialize().is_error()) {
+        (void)decoder->frame(0);
+    }
     return 0;
 }

+ 3 - 2
Meta/Lagom/Fuzzers/FuzzTGALoader.cpp

@@ -14,7 +14,8 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* data, size_t size)
     if (decoder_or_error.is_error())
         return 0;
     auto decoder = decoder_or_error.release_value();
-    decoder->initialize();
-    (void)decoder->frame(0);
+    if (!decoder->initialize().is_error()) {
+        (void)decoder->frame(0);
+    }
     return 0;
 }

+ 3 - 2
Meta/Lagom/Fuzzers/FuzzWebPLoader.cpp

@@ -14,7 +14,8 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* data, size_t size)
     if (decoder_or_error.is_error())
         return 0;
     auto decoder = decoder_or_error.release_value();
-    decoder->initialize();
-    (void)decoder->frame(0);
+    if (!decoder->initialize().is_error()) {
+        (void)decoder->frame(0);
+    }
     return 0;
 }

+ 4 - 4
Tests/LibGfx/TestICCProfile.cpp

@@ -24,7 +24,7 @@ TEST_CASE(png)
 {
     auto file = MUST(Core::MappedFile::map(TEST_INPUT("icc-v2.png"sv)));
     auto png = MUST(Gfx::PNGImageDecoderPlugin::create(file->bytes()));
-    EXPECT(png->initialize());
+    MUST(png->initialize());
     auto icc_bytes = MUST(png->icc_data());
     EXPECT(icc_bytes.has_value());
 
@@ -36,7 +36,7 @@ TEST_CASE(jpg)
 {
     auto file = MUST(Core::MappedFile::map(TEST_INPUT("icc-v4.jpg"sv)));
     auto jpg = MUST(Gfx::JPEGImageDecoderPlugin::create(file->bytes()));
-    EXPECT(jpg->initialize());
+    MUST(jpg->initialize());
     auto icc_bytes = MUST(jpg->icc_data());
     EXPECT(icc_bytes.has_value());
 
@@ -48,7 +48,7 @@ TEST_CASE(webp_extended_lossless)
 {
     auto file = MUST(Core::MappedFile::map(TEST_INPUT("extended-lossless.webp"sv)));
     auto webp = MUST(Gfx::WebPImageDecoderPlugin::create(file->bytes()));
-    EXPECT(webp->initialize());
+    MUST(webp->initialize());
     auto icc_bytes = MUST(webp->icc_data());
     EXPECT(icc_bytes.has_value());
 
@@ -60,7 +60,7 @@ TEST_CASE(webp_extended_lossy)
 {
     auto file = MUST(Core::MappedFile::map(TEST_INPUT("extended-lossy.webp"sv)));
     auto webp = MUST(Gfx::WebPImageDecoderPlugin::create(file->bytes()));
-    EXPECT(webp->initialize());
+    MUST(webp->initialize());
     auto icc_bytes = MUST(webp->icc_data());
     EXPECT(icc_bytes.has_value());
 

+ 29 - 29
Tests/LibGfx/TestImageDecoder.cpp

@@ -33,7 +33,7 @@ TEST_CASE(test_bmp)
     auto file = MUST(Core::MappedFile::map(TEST_INPUT("rgba32-1.bmp"sv)));
     EXPECT(Gfx::BMPImageDecoderPlugin::sniff(file->bytes()));
     auto plugin_decoder = MUST(Gfx::BMPImageDecoderPlugin::create(file->bytes()));
-    EXPECT(plugin_decoder->initialize());
+    MUST(plugin_decoder->initialize());
 
     EXPECT(plugin_decoder->frame_count());
     EXPECT(!plugin_decoder->is_animated());
@@ -48,7 +48,7 @@ TEST_CASE(test_gif)
     auto file = MUST(Core::MappedFile::map(TEST_INPUT("download-animation.gif"sv)));
     EXPECT(Gfx::GIFImageDecoderPlugin::sniff(file->bytes()));
     auto plugin_decoder = MUST(Gfx::GIFImageDecoderPlugin::create(file->bytes()));
-    EXPECT(plugin_decoder->initialize());
+    MUST(plugin_decoder->initialize());
 
     EXPECT(plugin_decoder->frame_count());
     EXPECT(plugin_decoder->is_animated());
@@ -63,7 +63,7 @@ TEST_CASE(test_not_ico)
     auto file = MUST(Core::MappedFile::map(TEST_INPUT("buggie.png"sv)));
     EXPECT(!Gfx::ICOImageDecoderPlugin::sniff(file->bytes()));
     auto plugin_decoder = MUST(Gfx::ICOImageDecoderPlugin::create(file->bytes()));
-    EXPECT(!plugin_decoder->initialize());
+    EXPECT(plugin_decoder->initialize().is_error());
 
     EXPECT(plugin_decoder->frame_count());
     EXPECT(!plugin_decoder->is_animated());
@@ -77,13 +77,13 @@ TEST_CASE(test_bmp_embedded_in_ico)
     auto file = MUST(Core::MappedFile::map(TEST_INPUT("serenity.ico"sv)));
     EXPECT(Gfx::ICOImageDecoderPlugin::sniff(file->bytes()));
     auto plugin_decoder = MUST(Gfx::ICOImageDecoderPlugin::create(file->bytes()));
-    EXPECT(plugin_decoder->initialize());
+    MUST(plugin_decoder->initialize());
 
     EXPECT(plugin_decoder->frame_count());
     EXPECT(!plugin_decoder->is_animated());
     EXPECT(!plugin_decoder->loop_count());
 
-    EXPECT(!plugin_decoder->frame(0).is_error());
+    MUST(plugin_decoder->frame(0));
 }
 
 TEST_CASE(test_jpeg_sof0_one_scan)
@@ -91,7 +91,7 @@ TEST_CASE(test_jpeg_sof0_one_scan)
     auto file = MUST(Core::MappedFile::map(TEST_INPUT("rgb24.jpg"sv)));
     EXPECT(Gfx::JPEGImageDecoderPlugin::sniff(file->bytes()));
     auto plugin_decoder = MUST(Gfx::JPEGImageDecoderPlugin::create(file->bytes()));
-    EXPECT(plugin_decoder->initialize());
+    MUST(plugin_decoder->initialize());
 
     EXPECT(plugin_decoder->frame_count());
     EXPECT(!plugin_decoder->is_animated());
@@ -106,7 +106,7 @@ TEST_CASE(test_jpeg_sof0_several_scans)
     auto file = MUST(Core::MappedFile::map(TEST_INPUT("several_scans.jpg"sv)));
     EXPECT(Gfx::JPEGImageDecoderPlugin::sniff(file->bytes()));
     auto plugin_decoder = MUST(Gfx::JPEGImageDecoderPlugin::create(file->bytes()));
-    EXPECT(plugin_decoder->initialize());
+    MUST(plugin_decoder->initialize());
 
     auto frame = MUST(plugin_decoder->frame(0));
     EXPECT_EQ(frame.image->size(), Gfx::IntSize(592, 800));
@@ -117,7 +117,7 @@ TEST_CASE(test_jpeg_rgb_components)
     auto file = MUST(Core::MappedFile::map(TEST_INPUT("rgb_components.jpg"sv)));
     EXPECT(Gfx::JPEGImageDecoderPlugin::sniff(file->bytes()));
     auto plugin_decoder = MUST(Gfx::JPEGImageDecoderPlugin::create(file->bytes()));
-    EXPECT(plugin_decoder->initialize());
+    MUST(plugin_decoder->initialize());
 
     auto frame = MUST(plugin_decoder->frame(0));
     EXPECT_EQ(frame.image->size(), Gfx::IntSize(592, 800));
@@ -128,7 +128,7 @@ TEST_CASE(test_jpeg_sof2_spectral_selection)
     auto file = MUST(Core::MappedFile::map(TEST_INPUT("spectral_selection.jpg"sv)));
     EXPECT(Gfx::JPEGImageDecoderPlugin::sniff(file->bytes()));
     auto plugin_decoder = MUST(Gfx::JPEGImageDecoderPlugin::create(file->bytes()));
-    EXPECT(plugin_decoder->initialize());
+    MUST(plugin_decoder->initialize());
 
     auto frame = MUST(plugin_decoder->frame(0));
     EXPECT_EQ(frame.image->size(), Gfx::IntSize(592, 800));
@@ -139,7 +139,7 @@ TEST_CASE(test_jpeg_sof0_several_scans_odd_number_mcu)
     auto file = MUST(Core::MappedFile::map(TEST_INPUT("several_scans_odd_number_mcu.jpg"sv)));
     EXPECT(Gfx::JPEGImageDecoderPlugin::sniff(file->bytes()));
     auto plugin_decoder = MUST(Gfx::JPEGImageDecoderPlugin::create(file->bytes()));
-    EXPECT(plugin_decoder->initialize());
+    MUST(plugin_decoder->initialize());
 
     auto frame = MUST(plugin_decoder->frame(0));
     EXPECT_EQ(frame.image->size(), Gfx::IntSize(600, 600));
@@ -150,7 +150,7 @@ TEST_CASE(test_jpeg_sof2_successive_aproximation)
     auto file = MUST(Core::MappedFile::map(TEST_INPUT("successive_approximation.jpg"sv)));
     EXPECT(Gfx::JPEGImageDecoderPlugin::sniff(file->bytes()));
     auto plugin_decoder = MUST(Gfx::JPEGImageDecoderPlugin::create(file->bytes()));
-    EXPECT(plugin_decoder->initialize());
+    MUST(plugin_decoder->initialize());
 
     auto frame = MUST(plugin_decoder->frame(0));
     EXPECT_EQ(frame.image->size(), Gfx::IntSize(600, 800));
@@ -161,7 +161,7 @@ TEST_CASE(test_jpeg_sof1_12bits)
     auto file = MUST(Core::MappedFile::map(TEST_INPUT("12-bit.jpg"sv)));
     EXPECT(Gfx::JPEGImageDecoderPlugin::sniff(file->bytes()));
     auto plugin_decoder = MUST(Gfx::JPEGImageDecoderPlugin::create(file->bytes()));
-    EXPECT(plugin_decoder->initialize());
+    MUST(plugin_decoder->initialize());
 
     auto frame = MUST(plugin_decoder->frame(0));
     EXPECT_EQ(frame.image->size(), Gfx::IntSize(320, 240));
@@ -172,7 +172,7 @@ TEST_CASE(test_jpeg_sof2_12bits)
     auto file = MUST(Core::MappedFile::map(TEST_INPUT("12-bit-progressive.jpg"sv)));
     EXPECT(Gfx::JPEGImageDecoderPlugin::sniff(file->bytes()));
     auto plugin_decoder = MUST(Gfx::JPEGImageDecoderPlugin::create(file->bytes()));
-    EXPECT(plugin_decoder->initialize());
+    MUST(plugin_decoder->initialize());
 
     auto frame = MUST(plugin_decoder->frame(0));
     EXPECT_EQ(frame.image->size(), Gfx::IntSize(320, 240));
@@ -183,7 +183,7 @@ TEST_CASE(test_pbm)
     auto file = MUST(Core::MappedFile::map(TEST_INPUT("buggie-raw.pbm"sv)));
     EXPECT(Gfx::PBMImageDecoderPlugin::sniff(file->bytes()));
     auto plugin_decoder = MUST(Gfx::PBMImageDecoderPlugin::create(file->bytes()));
-    EXPECT(plugin_decoder->initialize());
+    MUST(plugin_decoder->initialize());
 
     EXPECT(plugin_decoder->frame_count());
     EXPECT(!plugin_decoder->is_animated());
@@ -198,7 +198,7 @@ TEST_CASE(test_pgm)
     auto file = MUST(Core::MappedFile::map(TEST_INPUT("buggie-raw.pgm"sv)));
     EXPECT(Gfx::PGMImageDecoderPlugin::sniff(file->bytes()));
     auto plugin_decoder = MUST(Gfx::PGMImageDecoderPlugin::create(file->bytes()));
-    EXPECT(plugin_decoder->initialize());
+    MUST(plugin_decoder->initialize());
 
     EXPECT(plugin_decoder->frame_count());
     EXPECT(!plugin_decoder->is_animated());
@@ -213,7 +213,7 @@ TEST_CASE(test_png)
     auto file = MUST(Core::MappedFile::map(TEST_INPUT("buggie.png"sv)));
     EXPECT(Gfx::PNGImageDecoderPlugin::sniff(file->bytes()));
     auto plugin_decoder = MUST(Gfx::PNGImageDecoderPlugin::create(file->bytes()));
-    EXPECT(plugin_decoder->initialize());
+    MUST(plugin_decoder->initialize());
 
     EXPECT(plugin_decoder->frame_count());
     EXPECT(!plugin_decoder->is_animated());
@@ -228,7 +228,7 @@ TEST_CASE(test_ppm)
     auto file = MUST(Core::MappedFile::map(TEST_INPUT("buggie-raw.ppm"sv)));
     EXPECT(Gfx::PPMImageDecoderPlugin::sniff(file->bytes()));
     auto plugin_decoder = MUST(Gfx::PPMImageDecoderPlugin::create(file->bytes()));
-    EXPECT(plugin_decoder->initialize());
+    MUST(plugin_decoder->initialize());
 
     EXPECT(plugin_decoder->frame_count());
     EXPECT(!plugin_decoder->is_animated());
@@ -243,7 +243,7 @@ TEST_CASE(test_targa_bottom_left)
     auto file = MUST(Core::MappedFile::map(TEST_INPUT("buggie-bottom-left-uncompressed.tga"sv)));
     EXPECT(MUST(Gfx::TGAImageDecoderPlugin::validate_before_create(file->bytes())));
     auto plugin_decoder = MUST(Gfx::TGAImageDecoderPlugin::create(file->bytes()));
-    EXPECT(plugin_decoder->initialize());
+    MUST(plugin_decoder->initialize());
 
     EXPECT_EQ(plugin_decoder->frame_count(), 1u);
     EXPECT(!plugin_decoder->is_animated());
@@ -258,7 +258,7 @@ TEST_CASE(test_targa_top_left)
     auto file = MUST(Core::MappedFile::map(TEST_INPUT("buggie-top-left-uncompressed.tga"sv)));
     EXPECT(MUST(Gfx::TGAImageDecoderPlugin::validate_before_create(file->bytes())));
     auto plugin_decoder = MUST(Gfx::TGAImageDecoderPlugin::create(file->bytes()));
-    EXPECT(plugin_decoder->initialize());
+    MUST(plugin_decoder->initialize());
 
     EXPECT_EQ(plugin_decoder->frame_count(), 1u);
     EXPECT(!plugin_decoder->is_animated());
@@ -273,7 +273,7 @@ TEST_CASE(test_targa_bottom_left_compressed)
     auto file = MUST(Core::MappedFile::map(TEST_INPUT("buggie-bottom-left-compressed.tga"sv)));
     EXPECT(MUST(Gfx::TGAImageDecoderPlugin::validate_before_create(file->bytes())));
     auto plugin_decoder = MUST(Gfx::TGAImageDecoderPlugin::create(file->bytes()));
-    EXPECT(plugin_decoder->initialize());
+    MUST(plugin_decoder->initialize());
 
     EXPECT_EQ(plugin_decoder->frame_count(), 1u);
     EXPECT(!plugin_decoder->is_animated());
@@ -288,7 +288,7 @@ TEST_CASE(test_targa_top_left_compressed)
     auto file = MUST(Core::MappedFile::map(TEST_INPUT("buggie-top-left-compressed.tga"sv)));
     EXPECT(MUST(Gfx::TGAImageDecoderPlugin::validate_before_create(file->bytes())));
     auto plugin_decoder = MUST(Gfx::TGAImageDecoderPlugin::create(file->bytes()));
-    EXPECT(plugin_decoder->initialize());
+    MUST(plugin_decoder->initialize());
 
     EXPECT_EQ(plugin_decoder->frame_count(), 1u);
     EXPECT(!plugin_decoder->is_animated());
@@ -303,7 +303,7 @@ TEST_CASE(test_webp_simple_lossy)
     auto file = MUST(Core::MappedFile::map(TEST_INPUT("simple-vp8.webp"sv)));
     EXPECT(Gfx::WebPImageDecoderPlugin::sniff(file->bytes()));
     auto plugin_decoder = MUST(Gfx::WebPImageDecoderPlugin::create(file->bytes()));
-    EXPECT(plugin_decoder->initialize());
+    MUST(plugin_decoder->initialize());
 
     EXPECT_EQ(plugin_decoder->frame_count(), 1u);
     EXPECT(!plugin_decoder->is_animated());
@@ -319,7 +319,7 @@ TEST_CASE(test_webp_simple_lossless)
     auto file = MUST(Core::MappedFile::map(TEST_INPUT("simple-vp8l.webp"sv)));
     EXPECT(Gfx::WebPImageDecoderPlugin::sniff(file->bytes()));
     auto plugin_decoder = MUST(Gfx::WebPImageDecoderPlugin::create(file->bytes()));
-    EXPECT(plugin_decoder->initialize());
+    MUST(plugin_decoder->initialize());
 
     EXPECT_EQ(plugin_decoder->frame_count(), 1u);
     EXPECT(!plugin_decoder->is_animated());
@@ -345,7 +345,7 @@ TEST_CASE(test_webp_extended_lossy)
     auto file = MUST(Core::MappedFile::map(TEST_INPUT("extended-lossy.webp"sv)));
     EXPECT(Gfx::WebPImageDecoderPlugin::sniff(file->bytes()));
     auto plugin_decoder = MUST(Gfx::WebPImageDecoderPlugin::create(file->bytes()));
-    EXPECT(plugin_decoder->initialize());
+    MUST(plugin_decoder->initialize());
 
     EXPECT_EQ(plugin_decoder->frame_count(), 1u);
     EXPECT(!plugin_decoder->is_animated());
@@ -361,7 +361,7 @@ TEST_CASE(test_webp_extended_lossless)
     auto file = MUST(Core::MappedFile::map(TEST_INPUT("extended-lossless.webp"sv)));
     EXPECT(Gfx::WebPImageDecoderPlugin::sniff(file->bytes()));
     auto plugin_decoder = MUST(Gfx::WebPImageDecoderPlugin::create(file->bytes()));
-    EXPECT(plugin_decoder->initialize());
+    MUST(plugin_decoder->initialize());
 
     EXPECT_EQ(plugin_decoder->frame_count(), 1u);
     EXPECT(!plugin_decoder->is_animated());
@@ -392,7 +392,7 @@ TEST_CASE(test_webp_simple_lossless_color_index_transform)
     auto file = MUST(Core::MappedFile::map(TEST_INPUT("Qpalette.webp"sv)));
     EXPECT(Gfx::WebPImageDecoderPlugin::sniff(file->bytes()));
     auto plugin_decoder = MUST(Gfx::WebPImageDecoderPlugin::create(file->bytes()));
-    EXPECT(plugin_decoder->initialize());
+    MUST(plugin_decoder->initialize());
 
     EXPECT_EQ(plugin_decoder->frame_count(), 1u);
     EXPECT(!plugin_decoder->is_animated());
@@ -429,7 +429,7 @@ TEST_CASE(test_webp_simple_lossless_color_index_transform_pixel_bundling)
         auto file = MUST(Core::MappedFile::map(MUST(String::formatted("{}{}", TEST_INPUT(""), test_case.file_name))));
         EXPECT(Gfx::WebPImageDecoderPlugin::sniff(file->bytes()));
         auto plugin_decoder = MUST(Gfx::WebPImageDecoderPlugin::create(file->bytes()));
-        EXPECT(plugin_decoder->initialize());
+        MUST(plugin_decoder->initialize());
 
         EXPECT_EQ(plugin_decoder->frame_count(), 1u);
         EXPECT_EQ(plugin_decoder->size(), Gfx::IntSize(32, 32));
@@ -457,7 +457,7 @@ TEST_CASE(test_webp_simple_lossless_color_index_transform_pixel_bundling_odd_wid
     for (auto file_name : file_names) {
         auto file = MUST(Core::MappedFile::map(MUST(String::formatted("{}{}", TEST_INPUT(""), file_name))));
         auto plugin_decoder = MUST(Gfx::WebPImageDecoderPlugin::create(file->bytes()));
-        EXPECT(plugin_decoder->initialize());
+        MUST(plugin_decoder->initialize());
 
         EXPECT_EQ(plugin_decoder->frame_count(), 1u);
         EXPECT_EQ(plugin_decoder->size(), Gfx::IntSize(11, 11));
@@ -472,7 +472,7 @@ TEST_CASE(test_webp_extended_lossless_animated)
     auto file = MUST(Core::MappedFile::map(TEST_INPUT("extended-lossless-animated.webp"sv)));
     EXPECT(Gfx::WebPImageDecoderPlugin::sniff(file->bytes()));
     auto plugin_decoder = MUST(Gfx::WebPImageDecoderPlugin::create(file->bytes()));
-    EXPECT(plugin_decoder->initialize());
+    MUST(plugin_decoder->initialize());
 
     EXPECT_EQ(plugin_decoder->frame_count(), 8u);
     EXPECT(plugin_decoder->is_animated());

+ 1 - 1
Userland/Libraries/LibGUI/FileIconProvider.cpp

@@ -213,7 +213,7 @@ Icon FileIconProvider::icon_for_executable(DeprecatedString const& path)
             // FIXME: Use the ImageDecoder service.
             if (Gfx::PNGImageDecoderPlugin::sniff({ section->raw_data(), section->size() })) {
                 auto png_decoder = Gfx::PNGImageDecoderPlugin::create({ section->raw_data(), section->size() }).release_value_but_fixme_should_propagate_errors();
-                if (png_decoder->initialize()) {
+                if (!png_decoder->initialize().is_error()) {
                     auto frame_or_error = png_decoder->frame(0);
                     if (!frame_or_error.is_error()) {
                         bitmap = frame_or_error.value().image;

+ 2 - 2
Userland/Libraries/LibGfx/ImageFormats/BMPLoader.cpp

@@ -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)

+ 1 - 1
Userland/Libraries/LibGfx/ImageFormats/BMPLoader.h

@@ -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;

+ 6 - 3
Userland/Libraries/LibGfx/ImageFormats/DDSLoader.cpp

@@ -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)

+ 1 - 1
Userland/Libraries/LibGfx/ImageFormats/DDSLoader.h

@@ -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;

+ 3 - 2
Userland/Libraries/LibGfx/ImageFormats/GIFLoader.cpp

@@ -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)

+ 1 - 1
Userland/Libraries/LibGfx/ImageFormats/GIFLoader.h

@@ -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;

+ 10 - 11
Userland/Libraries/LibGfx/ImageFormats/ICOLoader.cpp

@@ -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()

+ 1 - 1
Userland/Libraries/LibGfx/ImageFormats/ICOLoader.h

@@ -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;

+ 2 - 2
Userland/Libraries/LibGfx/ImageFormats/ImageDecoder.cpp

@@ -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 {};

+ 1 - 1
Userland/Libraries/LibGfx/ImageFormats/ImageDecoder.h

@@ -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;

+ 2 - 2
Userland/Libraries/LibGfx/ImageFormats/JPEGLoader.cpp

@@ -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)

+ 1 - 1
Userland/Libraries/LibGfx/ImageFormats/JPEGLoader.h

@@ -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;

+ 4 - 2
Userland/Libraries/LibGfx/ImageFormats/PNGLoader.cpp

@@ -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)

+ 1 - 1
Userland/Libraries/LibGfx/ImageFormats/PNGLoader.h

@@ -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;

+ 1 - 1
Userland/Libraries/LibGfx/ImageFormats/PortableImageMapLoader.h

@@ -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;

+ 2 - 2
Userland/Libraries/LibGfx/ImageFormats/QOILoader.cpp

@@ -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)

+ 1 - 1
Userland/Libraries/LibGfx/ImageFormats/QOILoader.h

@@ -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; }

+ 4 - 2
Userland/Libraries/LibGfx/ImageFormats/TGALoader.cpp

@@ -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)

+ 1 - 1
Userland/Libraries/LibGfx/ImageFormats/TGALoader.h

@@ -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;

+ 5 - 3
Userland/Libraries/LibGfx/ImageFormats/WebPLoader.cpp

@@ -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)

+ 2 - 2
Userland/Libraries/LibGfx/ImageFormats/WebPLoader.h

@@ -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>);
 

+ 3 - 4
Userland/Libraries/LibPDF/Filter.cpp

@@ -272,10 +272,9 @@ PDFErrorOr<ByteBuffer> Filter::decode_dct(ReadonlyBytes bytes)
 {
     if (Gfx::JPEGImageDecoderPlugin::sniff({ bytes.data(), bytes.size() })) {
         auto decoder = Gfx::JPEGImageDecoderPlugin::create({ bytes.data(), bytes.size() }).release_value_but_fixme_should_propagate_errors();
-        if (decoder->initialize()) {
-            auto frame = TRY(decoder->frame(0));
-            return TRY(frame.image->serialize_to_byte_buffer());
-        }
+        TRY(decoder->initialize());
+        auto frame = TRY(decoder->frame(0));
+        return TRY(frame.image->serialize_to_byte_buffer());
     }
     return AK::Error::from_string_literal("Not a JPEG image!");
 };

+ 3 - 3
Userland/Services/SpiceAgent/SpiceAgent.cpp

@@ -143,19 +143,19 @@ void SpiceAgent::on_message_received()
             if (type == ClipboardType::PNG) {
                 if (Gfx::PNGImageDecoderPlugin::sniff({ data_buffer.data(), data_buffer.size() })) {
                     auto png_decoder = Gfx::PNGImageDecoderPlugin::create({ data_buffer.data(), data_buffer.size() }).release_value_but_fixme_should_propagate_errors();
-                    if (png_decoder->initialize())
+                    if (!png_decoder->initialize().is_error())
                         frame_or_error = png_decoder->frame(0);
                 }
             } else if (type == ClipboardType::BMP) {
                 if (Gfx::BMPImageDecoderPlugin::sniff({ data_buffer.data(), data_buffer.size() })) {
                     auto bmp_decoder = Gfx::BMPImageDecoderPlugin::create({ data_buffer.data(), data_buffer.size() }).release_value_but_fixme_should_propagate_errors();
-                    if (bmp_decoder->initialize())
+                    if (!bmp_decoder->initialize().is_error())
                         frame_or_error = bmp_decoder->frame(0);
                 }
             } else if (type == ClipboardType::JPEG) {
                 if (Gfx::JPEGImageDecoderPlugin::sniff({ data_buffer.data(), data_buffer.size() })) {
                     auto jpeg_decoder = Gfx::JPEGImageDecoderPlugin::create({ data_buffer.data(), data_buffer.size() }).release_value_but_fixme_should_propagate_errors();
-                    if (jpeg_decoder->initialize())
+                    if (!jpeg_decoder->initialize().is_error())
                         frame_or_error = jpeg_decoder->frame(0);
                 }
             } else {