[gimp] app: check for invalid offsets when loading XCF files



commit a842869247eb2cae2b40476b5d93f88d8b01aa27
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.

 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 7ef984273c..95bcd83f59 100644
--- a/app/xcf/xcf-load.c
+++ b/app/xcf/xcf-load.c
@@ -499,6 +499,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;
@@ -639,6 +646,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;
@@ -648,6 +662,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;
@@ -2143,6 +2158,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.
@@ -2286,6 +2302,7 @@ xcf_load_layer (XcfInfo    *info,
     gimp_layer_fix_format_space (layer, FALSE, FALSE);
 
   /* 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);
 
@@ -2295,6 +2312,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;
 
@@ -2318,6 +2340,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;
 
@@ -2373,6 +2400,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.
@@ -2405,9 +2433,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;
@@ -2458,6 +2493,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.
@@ -2491,9 +2527,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;
@@ -2535,6 +2578,7 @@ xcf_load_buffer (XcfInfo    *info,
   gint        width;
   gint        height;
   gint        bpp;
+  goffset     cur_offset;
 
   format = gegl_buffer_get_format (buffer);
 
@@ -2550,8 +2594,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]