[gimp/gimp-2-10] app: check for invalid offsets when loading XCF files



commit 744959433647bdefcdf00b3f0d575f6812cd0d6d
Author: Jacob Boerema <jgboerema gmail com>
Date:   Sun Jun 5 18:44:45 2022 -0400

    app: check for invalid offsets when loading XCF files
    
    More safety checks for detecting broken xcf files, also based on examining
    issue #8230.
    
    After reading an offset where layer, channel, etc. data is stored, we
    add a check to make sure that offset is not before where we read the
    offset value. Because the data is always written after the offset that
    points to it.
    
    (cherry picked from commit a842869247eb2cae2b40476b5d93f88d8b01aa27)

 app/xcf/xcf-load.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 53 insertions(+), 2 deletions(-)
---
diff --git a/app/xcf/xcf-load.c b/app/xcf/xcf-load.c
index f68909a038..da196bcdb2 100644
--- a/app/xcf/xcf-load.c
+++ b/app/xcf/xcf-load.c
@@ -485,6 +485,13 @@ xcf_load_image (Gimp     *gimp,
        */
       saved_pos = info->cp;
 
+      if (offset < saved_pos)
+        {
+          GIMP_LOG (XCF, "Invalid layer offset: %" G_GOFFSET_FORMAT
+                    " at offset: %" G_GOFFSET_FORMAT, offset, saved_pos);
+          goto error;
+        }
+
       /* seek to the layer offset */
       if (! xcf_seek_pos (info, offset, NULL))
         goto error;
@@ -625,6 +632,13 @@ xcf_load_image (Gimp     *gimp,
        */
       saved_pos = info->cp;
 
+      if (offset < saved_pos)
+        {
+          GIMP_LOG (XCF, "Invalid channel offset: %" G_GOFFSET_FORMAT
+                    " at offset: % "G_GOFFSET_FORMAT, offset, saved_pos);
+          goto error;
+        }
+
       /* seek to the channel offset */
       if (! xcf_seek_pos (info, offset, NULL))
         goto error;
@@ -634,6 +648,7 @@ xcf_load_image (Gimp     *gimp,
       if (!channel)
         {
           n_broken_channels++;
+          GIMP_LOG (XCF, "Failed to load channel.");
 
           if (! xcf_seek_pos (info, saved_pos, NULL))
             goto error;
@@ -1891,6 +1906,7 @@ xcf_load_layer (XcfInfo    *info,
   const Babl        *format;
   gboolean           is_fs_drawable;
   gchar             *name;
+  goffset            cur_offset;
 
   /* check and see if this is the drawable the floating selection
    *  is attached to. if it is then we'll do the attachment in our caller.
@@ -2008,6 +2024,7 @@ xcf_load_layer (XcfInfo    *info,
     }
 
   /* read the hierarchy and layer mask offsets */
+  cur_offset = info->cp;
   xcf_read_offset (info, &hierarchy_offset,  1);
   xcf_read_offset (info, &layer_mask_offset, 1);
 
@@ -2017,6 +2034,11 @@ xcf_load_layer (XcfInfo    *info,
    */
   if (! gimp_viewable_get_children (GIMP_VIEWABLE (layer)))
     {
+      if (hierarchy_offset < cur_offset)
+        {
+          GIMP_LOG (XCF, "Invalid layer hierarchy offset!");
+          goto error;
+        }
       if (! xcf_seek_pos (info, hierarchy_offset, NULL))
         goto error;
 
@@ -2040,6 +2062,11 @@ xcf_load_layer (XcfInfo    *info,
   /* read in the layer mask */
   if (layer_mask_offset != 0)
     {
+      if (layer_mask_offset < cur_offset)
+        {
+          GIMP_LOG (XCF, "Invalid layer mask offset!");
+          goto error;
+        }
       if (! xcf_seek_pos (info, layer_mask_offset, NULL))
         goto error;
 
@@ -2096,6 +2123,7 @@ xcf_load_channel (XcfInfo   *info,
   gboolean     is_fs_drawable;
   gchar       *name;
   GimpRGB      color = { 0.0, 0.0, 0.0, GIMP_OPACITY_OPAQUE };
+  goffset      cur_offset;
 
   /* check and see if this is the drawable the floating selection
    *  is attached to. if it is then we'll do the attachment in our caller.
@@ -2128,9 +2156,16 @@ xcf_load_channel (XcfInfo   *info,
 
   xcf_progress_update (info);
 
-  /* read the hierarchy and layer mask offsets */
+  /* read the hierarchy offset */
+  cur_offset = info->cp;
   xcf_read_offset (info, &hierarchy_offset, 1);
 
+  if (hierarchy_offset < cur_offset)
+    {
+      GIMP_LOG (XCF, "Invalid hierarchy offset!");
+      goto error;
+    }
+
   /* read in the hierarchy */
   if (! xcf_seek_pos (info, hierarchy_offset, NULL))
     goto error;
@@ -2174,6 +2209,7 @@ xcf_load_layer_mask (XcfInfo   *info,
   gboolean       is_fs_drawable;
   gchar         *name;
   GimpRGB        color = { 0.0, 0.0, 0.0, GIMP_OPACITY_OPAQUE };
+  goffset        cur_offset;
 
   /* check and see if this is the drawable the floating selection
    *  is attached to. if it is then we'll do the attachment in our caller.
@@ -2207,9 +2243,16 @@ xcf_load_layer_mask (XcfInfo   *info,
 
   xcf_progress_update (info);
 
-  /* read the hierarchy and layer mask offsets */
+  /* read the hierarchy offset */
+  cur_offset = info->cp;
   xcf_read_offset (info, &hierarchy_offset, 1);
 
+  if (hierarchy_offset < cur_offset)
+    {
+      GIMP_LOG (XCF, "Invalid hierarchy offset!");
+      goto error;
+    }
+
   /* read in the hierarchy */
   if (! xcf_seek_pos (info, hierarchy_offset, NULL))
     goto error;
@@ -2247,6 +2290,7 @@ xcf_load_buffer (XcfInfo    *info,
   gint        width;
   gint        height;
   gint        bpp;
+  goffset     cur_offset;
 
   format = gegl_buffer_get_format (buffer);
 
@@ -2262,8 +2306,15 @@ xcf_load_buffer (XcfInfo    *info,
       bpp    != babl_format_get_bytes_per_pixel (format))
     return FALSE;
 
+  cur_offset = info->cp;
   xcf_read_offset (info, &offset, 1); /* top level */
 
+  if (offset < cur_offset)
+    {
+      GIMP_LOG (XCF, "Invalid buffer offset!");
+      return FALSE;
+    }
+
   /* seek to the level offset */
   if (! xcf_seek_pos (info, offset, NULL))
     return FALSE;


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