[gthumb: 1/5] Fixed crash in case of some malformed jpegs




commit 9729b8688d5d67c01deabea46ad469ec517250c5
Author: Joerg Fellmann <dev fellnet de>
Date:   Mon May 25 13:06:55 2020 +0200

    Fixed crash in case of some malformed jpegs
    
    With certain malformed jpegs the call to jpeg_finish_decompress
    caused a long jump back to stop_loading. This jump overwrote the
    value of the surface pointer which should be NULL which in turn
    caused a cairo assert when trying to get a reference to a surface
    with ref_count = 0.
    
    Also moved the cleanup of in_buffer out of the !finished scope,
    as it seems this would otherwise be a potential leak.

 extensions/cairo_io/cairo-image-surface-jpeg.c | 79 +++++++++++++-------------
 1 file changed, 41 insertions(+), 38 deletions(-)
---
diff --git a/extensions/cairo_io/cairo-image-surface-jpeg.c b/extensions/cairo_io/cairo-image-surface-jpeg.c
index 8ab26fd2a..38755384f 100644
--- a/extensions/cairo_io/cairo-image-surface-jpeg.c
+++ b/extensions/cairo_io/cairo-image-surface-jpeg.c
@@ -183,7 +183,7 @@ _cairo_image_surface_create_from_jpeg (GInputStream  *istream,
        unsigned char                 *p_buffer;
        int                            x;
        gboolean                       read_all_scanlines = FALSE;
-       gboolean                       finished = FALSE;
+       volatile gboolean                       finished = FALSE;
 
        image = gth_image_new ();
        surface = NULL;
@@ -564,59 +564,62 @@ _cairo_image_surface_create_from_jpeg (GInputStream  *istream,
 
        stop_loading:
 
-       if (surface != NULL) {
-               cairo_surface_mark_dirty (surface);
+       if (! finished) {
+               finished = TRUE;
 
-               if (! g_cancellable_is_cancelled (cancellable)) {
-                       int original_width;
-                       int original_height;
+               if (surface != NULL) {
+                       cairo_surface_mark_dirty (surface);
 
-                       /* Set the original dimensions */
+                       if (! g_cancellable_is_cancelled (cancellable)) {
+                               int original_width;
+                               int original_height;
 
-                       if ((orientation == GTH_TRANSFORM_ROTATE_90)
-                            || (orientation == GTH_TRANSFORM_ROTATE_270)
-                            || (orientation == GTH_TRANSFORM_TRANSPOSE)
-                            || (orientation == GTH_TRANSFORM_TRANSVERSE))
-                       {
-                               original_width = srcinfo.image_height;
-                               original_height = srcinfo.image_width;
-                       }
-                       else {
-                               original_width = srcinfo.image_width;
-                               original_height = srcinfo.image_height;
-                       }
+                               /* Set the original dimensions */
 
-                       _cairo_metadata_set_original_size (metadata, original_width, original_height);
+                               if ((orientation == GTH_TRANSFORM_ROTATE_90)
+                                        ||     (orientation == GTH_TRANSFORM_ROTATE_270)
+                                        ||     (orientation == GTH_TRANSFORM_TRANSPOSE)
+                                        ||     (orientation == GTH_TRANSFORM_TRANSVERSE))
+                               {
+                                       original_width = srcinfo.image_height;
+                                       original_height = srcinfo.image_width;
+                               }
+                               else {
+                                       original_width = srcinfo.image_width;
+                                       original_height = srcinfo.image_height;
+                               }
 
-                       if (original_width_p != NULL)
-                               *original_width_p = original_width;
-                       if (original_height_p != NULL)
-                               *original_height_p = original_height;
-                       if (loaded_original_p != NULL)
-                               *loaded_original_p = ! load_scaled;
+                               _cairo_metadata_set_original_size (metadata, original_width, original_height);
 
-                       /*_cairo_image_surface_set_attribute_int (surface, "Image::Rotation", rotation); 
FIXME*/
-                       /* FIXME _cairo_image_surface_set_attribute (surface, "Jpeg::ColorSpace", 
jpeg_color_space_name (srcinfo.jpeg_color_space)); */
+                               if (original_width_p != NULL)
+                                       *original_width_p = original_width;
+                               if (original_height_p != NULL)
+                                       *original_height_p = original_height;
+                               if (loaded_original_p != NULL)
+                                       *loaded_original_p = ! load_scaled;
 
-                       gth_image_set_cairo_surface (image, surface);
-               }
-               else
-                       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CANCELLED, "");
+                               /*_cairo_image_surface_set_attribute_int (surface, "Image::Rotation", 
rotation); FIXME*/
+                               /* FIXME _cairo_image_surface_set_attribute (surface, "Jpeg::ColorSpace", 
jpeg_color_space_name (srcinfo.jpeg_color_space)); */
 
-               cairo_surface_destroy (surface);
-               surface = NULL; /* ignore other jpeg errors */
-       }
+                               gth_image_set_cairo_surface (image, surface);
+                       }
+                       else
+                               g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CANCELLED, "");
+
+                       cairo_surface_destroy (surface);
+                       surface = NULL; /* ignore other jpeg errors */
+                       
+               }
 
-       if (! finished) {
-               finished = TRUE;
                if (read_all_scanlines)
                        jpeg_finish_decompress (&srcinfo);
                else
                        jpeg_abort_decompress (&srcinfo);
                jpeg_destroy_decompress (&srcinfo);
-               g_free (in_buffer);
        }
 
+       g_free (in_buffer);
+
        return image;
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]