Ver Fonte

LibGfx: Make all image decoders reject image sizes above 16384 pixels

Let's just say no to shenanigans by capping images at 16384 pixels both
wide and tall. If a day comes in the future where we need to handle
images larger than this, we can deal with it then.
Andreas Kling há 4 anos atrás
pai
commit
edf01803cd

+ 5 - 0
Libraries/LibGfx/BMPLoader.cpp

@@ -518,6 +518,11 @@ static bool decode_bmp_core_dib(BMPLoadingContext& context, Streamer& streamer)
         return false;
     }
 
+    if (static_cast<size_t>(core.width) > maximum_width_for_decoded_images || static_cast<size_t>(abs(core.height)) > maximum_height_for_decoded_images) {
+        dbgln("This BMP is too large for comfort: {}x{}", core.width, abs(core.height));
+        return false;
+    }
+
     auto color_planes = streamer.read_u16();
     if (color_planes != 1) {
         IF_BMP_DEBUG(dbg() << "BMP has an invalid number of color planes: " << color_planes);

+ 5 - 0
Libraries/LibGfx/GIFLoader.cpp

@@ -424,6 +424,11 @@ static bool load_gif_frame_descriptors(GIFLoadingContext& context)
     if (stream.handle_any_error())
         return false;
 
+    if (context.logical_screen.width > maximum_width_for_decoded_images || context.logical_screen.height > maximum_height_for_decoded_images) {
+        dbgln("This GIF is too large for comfort: {}x{}", context.logical_screen.width, context.logical_screen.height);
+        return false;
+    }
+
     u8 gcm_info = 0;
     stream >> gcm_info;
 

+ 3 - 0
Libraries/LibGfx/ImageDecoder.h

@@ -36,6 +36,9 @@ namespace Gfx {
 
 class Bitmap;
 
+static constexpr size_t maximum_width_for_decoded_images = 16384;
+static constexpr size_t maximum_height_for_decoded_images = 16384;
+
 struct ImageFrameDescriptor {
     RefPtr<Bitmap> image;
     int duration { 0 };

+ 6 - 0
Libraries/LibGfx/JPGLoader.cpp

@@ -776,6 +776,12 @@ static bool read_start_of_frame(InputMemoryStream& stream, JPGLoadingContext& co
 #endif
         return false;
     }
+
+    if (context.frame.width > maximum_width_for_decoded_images || context.frame.height > maximum_height_for_decoded_images) {
+        dbgln("This JPEG is too large for comfort: {}x{}", context.frame.width, context.frame.height);
+        return false;
+    }
+
     set_macroblock_metadata(context);
 
     stream >> context.component_count;

+ 2 - 2
Libraries/LibGfx/PBMLoader.cpp

@@ -60,8 +60,8 @@ struct PBMLoadingContext {
     State state { State::NotDecoded };
     const u8* data { nullptr };
     size_t data_size { 0 };
-    int width { -1 };
-    int height { -1 };
+    size_t width { 0 };
+    size_t height { 0 };
     RefPtr<Gfx::Bitmap> bitmap;
 };
 

+ 2 - 2
Libraries/LibGfx/PNGLoader.cpp

@@ -853,8 +853,8 @@ static bool process_IHDR(ReadonlyBytes data, PNGLoadingContext& context)
         return false;
     auto& ihdr = *(const PNG_IHDR*)data.data();
 
-    if (ihdr.width > NumericLimits<i32>::max() || ihdr.height > NumericLimits<i32>::max()) {
-        dbgln("PNG has invalid geometry {}x{}", (u32)ihdr.width, (u32)ihdr.height);
+    if (ihdr.width > maximum_width_for_decoded_images || ihdr.height > maximum_height_for_decoded_images) {
+        dbgln("This PNG is too large for comfort: {}x{}", (u32)ihdr.width, (u32)ihdr.height);
         return false;
     }
 

+ 15 - 6
Libraries/LibGfx/PortableImageLoaderCommon.h

@@ -1,5 +1,6 @@
 /*
- * Copyright (c) 2020, the SerenityOS developers, Hüseyin ASLITÜRK <asliturk@hotmail.com>
+ * Copyright (c) 2020, Hüseyin Aslıtürk <asliturk@hotmail.com>
+ * Copyright (c) 2020, the SerenityOS developers
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,7 +27,6 @@
 
 #pragma once
 
-#include "Streamer.h"
 #include <AK/Array.h>
 #include <AK/Endian.h>
 #include <AK/LexicalPath.h>
@@ -36,6 +36,10 @@
 #include <AK/StringBuilder.h>
 #include <AK/Types.h>
 #include <AK/Vector.h>
+#include <LibGfx/Bitmap.h>
+#include <LibGfx/Color.h>
+#include <LibGfx/ImageDecoder.h>
+#include <LibGfx/Streamer.h>
 
 //#define PORTABLE_IMAGE_LOADER_DEBUG
 
@@ -216,8 +220,8 @@ template<typename TContext>
 static void set_adjusted_pixels(TContext& context, const AK::Vector<Gfx::Color>& color_data)
 {
     size_t index = 0;
-    for (int y = 0; y < context.height; ++y) {
-        for (int x = 0; x < context.width; ++x) {
+    for (size_t y = 0; y < context.height; ++y) {
+        for (size_t x = 0; x < context.width; ++x) {
             Color color = color_data.at(index);
             if (context.max_val < 255) {
                 color = adjust_color(context.max_val, color);
@@ -232,8 +236,8 @@ template<typename TContext>
 static void set_pixels(TContext& context, const AK::Vector<Gfx::Color>& color_data)
 {
     size_t index = 0;
-    for (int y = 0; y < context.height; ++y) {
-        for (int x = 0; x < context.width; ++x) {
+    for (size_t y = 0; y < context.height; ++y) {
+        for (size_t x = 0; x < context.width; ++x) {
             context.bitmap->set_pixel(x, y, color_data.at(index));
             index++;
         }
@@ -267,6 +271,11 @@ static bool decode(TContext& context)
     if (!read_height(context, streamer))
         return false;
 
+    if (context.width > maximum_width_for_decoded_images || context.height > maximum_height_for_decoded_images) {
+        dbgln("This portable network image is too large for comfort: {}x{}", context.width, context.height);
+        return false;
+    }
+
     if (!read_white_space(context, streamer))
         return false;