Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 95931d60fe986cb88dac43d05c397ef3 > files > 8

gimp-2.2.13-2.0.10.el5.src.rpm

From 1ccd8d999d3781d336f1495f8ad57c8ca8b48f37 Mon Sep 17 00:00:00 2001
From: Nils Philippsen <nils@redhat.com>
Date: Fri, 20 Jul 2012 15:41:10 +0200
Subject: [PATCH] patch: CVE-2012-3403

Squashed commit of the following:

commit 7e60d0f3f18746acb118c49b492569b75927e9bb
Author: Nils Philippsen <nils@redhat.com>
Date:   Tue Jul 17 15:06:16 2012 +0200

    CEL: use statically allocated palette buffer
    (backported from commit db603abe493b7a8e7759b12efea4bc25c48c2400)

commit 02a3d5eda0a394e217281f20535ad3094d5b5ab7
Author: Nils Philippsen <nils@redhat.com>
Date:   Tue Jul 17 15:04:00 2012 +0200

    CEL: validate header data (CVE-2012-3403)
    (backported from commit 9d9e4aa5917420ccc90fa60fb19e4e03bc966776)

commit 20c1d140f9926d65b5aff95c05e8e8cd8d2e3488
Author: Nils Philippsen <nils@redhat.com>
Date:   Tue Jul 17 12:58:46 2012 +0200

    CEL: check fread()/g_fopen() return values for errors
    (backported from commit 54ae056bfee8f2e6e04578cd2eb7956fefff8c44)
---
 plug-ins/common/CEL.c |  249 ++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 204 insertions(+), 45 deletions(-)

diff --git a/plug-ins/common/CEL.c b/plug-ins/common/CEL.c
index 065c989..d89f6f8 100644
--- a/plug-ins/common/CEL.c
+++ b/plug-ins/common/CEL.c
@@ -47,7 +47,8 @@ static void run   (const gchar      *name,
                    gint             *nreturn_vals,
                    GimpParam       **return_vals);
 
-static gint      load_palette   (FILE        *fp,
+static gint      load_palette   (const gchar  *file,
+                                 FILE        *fp,
                                  guchar       palette[]);
 static gint32    load_image     (const gchar *file,
                                  const gchar *brief);
@@ -56,7 +57,7 @@ static gint      save_image     (const gchar *file,
                                  gint32       image,
                                  gint32       layer);
 static void      palette_dialog (const gchar *title);
-static gboolean  need_palette   (const gchar *file);
+static gint      need_palette   (const gchar *file);
 
 
 /* Globals... */
@@ -150,6 +151,7 @@ run (const gchar      *name,
   GimpPDBStatusType  status = GIMP_PDB_SUCCESS;
   gint32             image;
   GimpExportReturn   export = GIMP_EXPORT_CANCEL;
+  gint               needs_palette = 0;
 
   run_mode = param[0].data.d_int32;
 
@@ -187,20 +189,32 @@ run (const gchar      *name,
       else if (run_mode == GIMP_RUN_INTERACTIVE)
         {
           /* Let user choose KCF palette (cancel ignores) */
-          if (need_palette (param[1].data.d_string))
-            palette_dialog (_("Load KISS Palette"));
+          needs_palette = need_palette (param[1].data.d_string);
 
-          gimp_set_data ("file_cel_save:length", &data_length, sizeof (gsize));
-          gimp_set_data ("file_cel_save:data", palette_file, data_length);
-        }
+          if (needs_palette != -1)
+            {
+              if (needs_palette)
+                palette_dialog (_("Load KISS Palette"));
 
-      image = load_image (param[1].data.d_string, param[2].data.d_string);
+              gimp_set_data ("file_cel_save:length", &data_length, sizeof (gsize));
+              gimp_set_data ("file_cel_save:data", palette_file, data_length);
+            }
+        }
 
-      if (image != -1)
+      if (needs_palette != -1)
         {
-          *nreturn_vals = 2;
-          values[1].type         = GIMP_PDB_IMAGE;
-          values[1].data.d_image = image;
+          image = load_image (param[1].data.d_string, param[2].data.d_string);
+
+          if (image != -1)
+            {
+              *nreturn_vals = 2;
+              values[1].type         = GIMP_PDB_IMAGE;
+              values[1].data.d_image = image;
+            }
+          else
+            {
+              status = GIMP_PDB_EXECUTION_ERROR;
+            }
         }
       else
         {
@@ -256,19 +270,31 @@ run (const gchar      *name,
 }
 
 /* Peek into the file to determine whether we need a palette */
-static gboolean
+static gint
 need_palette (const gchar *file)
 {
   FILE   *fp;
   guchar  header[32];
+  size_t  n_read;
 
   fp = fopen (file, "rb");
-  if (!fp)
-    return FALSE;
+  if (fp == NULL)
+    {
+      g_message (_("Could not open '%s' for reading: %s"),
+                 gimp_filename_to_utf8 (file), g_strerror (errno));
+      return -1;
+    }
+
+  n_read = fread (header, 32, 1, fp);
 
-  fread (header, 32, 1, fp);
   fclose (fp);
 
+  if (n_read < 1)
+    {
+      g_message (_("EOF or error while reading image header"));
+      return -1;
+    }
+
   return (header[5] < 32);
 }
 
@@ -280,11 +306,12 @@ load_image (const gchar *file,
 {
   FILE      *fp;            /* Read file pointer */
   gchar     *progress;      /* Title for progress display */
-  guchar     header[32];    /* File header */
+  guchar     header[32],    /* File header */
+             file_mark,     /* KiSS file type */
+             bpp;           /* Bits per pixel */
   gint       height, width, /* Dimensions of image */
              offx, offy,    /* Layer offets */
-             colours,       /* Number of colours */
-             bpp;           /* Bits per pixel */
+             colours;       /* Number of colours */
 
   gint32     image,         /* Image */
              layer;         /* Layer */
@@ -295,6 +322,7 @@ load_image (const gchar *file,
   GimpPixelRgn  pixel_rgn;  /* Pixel region for layer */
 
   gint       i, j, k;       /* Counters */
+  size_t     n_read;        /* Number of items read from file */
 
 
   /* Open the file for reading */
@@ -314,7 +342,13 @@ load_image (const gchar *file,
 
   /* Get the image dimensions and create the image... */
 
-  fread (header, 4, 1, fp);
+  n_read = fread (header, 4, 1, fp);
+
+  if (n_read < 1)
+    {
+      g_message (_("EOF or error while reading image header"));
+      return -1;
+    }
 
   if (strncmp (header, "KiSS", 4))
     {
@@ -327,18 +361,49 @@ load_image (const gchar *file,
     }
   else
     { /* New-style image file, read full header */
-      fread (header, 28, 1, fp);
+      n_read = fread (header, 28, 1, fp);
+
+      if (n_read < 1)
+        {
+          g_message (_("EOF or error while reading image header"));
+          return -1;
+        }
+
+      file_mark = header[0];
+      if (file_mark != 0x20 && file_mark != 0x21)
+        {
+          g_message (_("is not a CEL image file"));
+          return -1;
+        }
+
       bpp = header[1];
-      if (bpp == 24)
-        colours = -1;
-      else
-        colours = (1 << header[1]);
+      switch (bpp)
+        {
+        case 4:
+        case 8:
+        case 32:
+          colours = (1 << bpp);
+          break;
+        default:
+          g_message (_("illegal bpp value in image: %hhu"), bpp);
+          return -1;
+        }
+
       width = header[4] + (256 * header[5]);
       height = header[6] + (256 * header[7]);
       offx = header[8] + (256 * header[9]);
       offy = header[10] + (256 * header[11]);
     }
 
+  if ((width == 0) || (height == 0) || (width + offx > GIMP_MAX_IMAGE_SIZE) ||
+      (height + offy > GIMP_MAX_IMAGE_SIZE))
+    {
+      g_message (_("illegal image dimensions: width: %d, horizontal offset: "
+                 "%d, height: %d, vertical offset: %d"),
+                 width, offx, height, offy);
+      return -1;
+    }
+
   if (bpp == 32)
     image = gimp_image_new (width + offx, height + offy, GIMP_RGB);
   else
@@ -378,7 +443,14 @@ load_image (const gchar *file,
       switch (bpp)
         {
         case 4:
-          fread (buffer, (width+1)/2, 1, fp);
+          n_read = fread (buffer, (width+1)/2, 1, fp);
+
+          if (n_read < 1)
+            {
+              g_message (_("EOF or error while reading image data"));
+              return -1;
+            }
+
           for (j = 0, k = 0; j < width*2; j+= 4, ++k)
             {
               if (buffer[k] / 16 == 0)
@@ -405,7 +477,14 @@ load_image (const gchar *file,
           break;
 
         case 8:
-          fread (buffer, width, 1, fp);
+          n_read = fread (buffer, width, 1, fp);
+
+          if (n_read < 1)
+            {
+              g_message (_("EOF or error while reading image data"));
+              return -1;
+            }
+
           for (j = 0, k = 0; j < width*2; j+= 2, ++k)
             {
               if (buffer[k] == 0)
@@ -422,7 +501,14 @@ load_image (const gchar *file,
           break;
 
         case 32:
-          fread (line, width*4, 1, fp);
+          n_read = fread (line, width*4, 1, fp);
+
+          if (n_read < 1)
+            {
+              g_message (_("EOF or error while reading image data"));
+              return -1;
+            }
+
           /* The CEL file order is BGR so we need to swap B and R
            * to get the Gimp RGB order.
            */
@@ -452,7 +538,7 @@ load_image (const gchar *file,
   if (bpp != 32)
     {
       /* Use palette from file or otherwise default grey palette */
-      palette = g_new (guchar, colours*3);
+      guchar palette[256*3];
 
       /* Open the file for reading if user picked one */
       if (palette_file == NULL)
@@ -462,12 +548,22 @@ load_image (const gchar *file,
       else
         {
           fp = fopen (palette_file, "r");
+
+          if (fp == NULL)
+            {
+              g_message (_("Could not open '%s' for reading: %s"),
+                         gimp_filename_to_utf8 (palette_file),
+                         g_strerror (errno));
+              return -1;
+            }
         }
 
       if (fp != NULL)
         {
-          colours = load_palette (fp, palette);
+          colours = load_palette (palette_file, fp, palette);
           fclose (fp);
+          if (colours < 0)
+            return -1;
         }
       else
         {
@@ -478,10 +574,6 @@ load_image (const gchar *file,
         }
 
       gimp_image_set_colormap (image, palette + 3, colours - 1);
-
-      /* Close palette file, give back allocated memory */
-
-      g_free (palette);
     }
 
   /* Now get everything redrawn and hand back the finished image */
@@ -493,32 +585,91 @@ load_image (const gchar *file,
 }
 
 static gint
-load_palette (FILE   *fp,
+load_palette (const gchar *file,
+              FILE   *fp,
               guchar  palette[])
 {
   guchar        header[32];     /* File header */
   guchar        buffer[2];
-  int           i, bpp, colours= 0;
+  guchar        file_mark, bpp;
+  gint          i, colours = 0;
+  size_t        n_read;
+
+  n_read = fread (header, 4, 1, fp);
+
+  if (n_read < 1)
+    {
+      g_message (_("'%s': EOF or error while reading palette header"),
+                 gimp_filename_to_utf8 (file));
+      return -1;
+    }
 
-  fread (header, 4, 1, fp);
   if (!strncmp(header, "KiSS", 4))
     {
-      fread (header+4, 28, 1, fp);
+      n_read = fread (header+4, 28, 1, fp);
+
+      if (n_read < 1)
+        {
+          g_message (_("'%s': EOF or error while reading palette header"),
+                     gimp_filename_to_utf8 (file));
+          return -1;
+        }
+
+      file_mark = header[4];
+      if (file_mark != 0x10)
+        {
+          g_message (_("'%s': is not a KCF palette file"),
+                     gimp_filename_to_utf8 (file));
+          return -1;
+        }
+
       bpp = header[5];
+      if (bpp != 12 && bpp != 24)
+        {
+          g_message (_("'%s': illegal bpp value in palette: %hhu"),
+                     gimp_filename_to_utf8 (file), bpp);
+          return -1;
+        }
+
       colours = header[8] + header[9] * 256;
-      if (bpp == 12)
+      if (colours != 16 && colours != 256)
+        {
+          g_message (_("'%s': illegal number of colors: %u"),
+                     gimp_filename_to_utf8 (file), colours);
+          return -1;
+        }
+
+      switch (bpp)
         {
+        case 12:
           for (i= 0; i < colours; ++i)
             {
-              fread (buffer, 1, 2, fp);
+              n_read = fread (buffer, 1, 2, fp);
+
+              if (n_read < 2)
+                {
+                  g_message (_("'%s': EOF or error while reading palette data"),
+                             gimp_filename_to_utf8 (file));
+                  return -1;
+                }
+
               palette[i*3]= buffer[0] & 0xf0;
               palette[i*3+1]= (buffer[1] & 0x0f) * 16;
               palette[i*3+2]= (buffer[0] & 0x0f) * 16;
             }
-        }
-      else
-        {
-          fread (palette, colours, 3, fp);
+          break;
+        case 24:
+          n_read = fread (palette, colours, 3, fp);
+
+          if (n_read < 3)
+            {
+              g_message (_("'%s': EOF or error while reading palette data"),
+                         gimp_filename_to_utf8 (file));
+              return -1;
+            }
+          break;
+        default:
+          g_assert_not_reached ();
         }
     }
   else
@@ -527,7 +678,15 @@ load_palette (FILE   *fp,
       fseek (fp, 0, SEEK_SET);
       for (i= 0; i < colours; ++i)
         {
-          fread (buffer, 1, 2, fp);
+          n_read = fread (buffer, 1, 2, fp);
+
+          if (n_read < 2)
+            {
+              g_message (_("'%s': EOF or error while reading palette data"),
+                         gimp_filename_to_utf8 (file));
+              return -1;
+            }
+
           palette[i*3] = buffer[0] & 0xf0;
           palette[i*3+1] = (buffer[1] & 0x0f) * 16;
           palette[i*3+2] = (buffer[0] & 0x0f) * 16;
-- 
1.7.10.4