File gegl-ppm-segfault.patch of Package gegl
From 021add95ac3bcd7f60932c63c7c1ed5cec765c4d Mon Sep 17 00:00:00 2001
From: Nils Philippsen <nils@redhat.com>
Date: Tue, 16 Oct 2012 16:58:27 +0200
Subject: [PATCH 1/3] ppm-load: CVE-2012-4433: don't overflow memory
allocation
Carefully selected width/height values could cause the size of a later
allocation to overflow, resulting in a buffer much too small to store
the data which would then written beyond its end.
From 147388a43d1a67000a409163098abec30a4194c0 Mon Sep 17 00:00:00 2001
From: Nils Philippsen <nils@redhat.com>
Date: Tue, 16 Oct 2012 16:56:40 +0200
Subject: [PATCH 2/3] ppm-load: CVE-2012-4433: add plausibility checks for
header fields
Refuse values that are non-decimal, negative or overflow the target
type.
From 7085d5362b131726bdd8fa3e5bf30217849046e7 Mon Sep 17 00:00:00 2001
From: Nils Philippsen <nils@redhat.com>
Date: Tue, 16 Oct 2012 16:57:37 +0200
Subject: [PATCH 3/3] ppm-load: bring comment in line with reality
Index: gegl-0.1.2/operations/external/ppm-load.c
===================================================================
--- gegl-0.1.2.orig/operations/external/ppm-load.c
+++ gegl-0.1.2/operations/external/ppm-load.c
@@ -36,6 +36,7 @@ gegl_chant_file_path (path, _("File"), "
#include "gegl-chant.h"
#include <stdio.h>
#include <stdlib.h>
+#include <errno.h>
typedef enum {
PIXMAP_ASCII = 51,
@@ -44,9 +45,9 @@ typedef enum {
typedef struct {
map_type type;
- gint width;
- gint height;
- gint size;
+ glong width;
+ glong height;
+ glong size;
gint maxval;
guchar *data;
} pnm_struct;
@@ -67,7 +68,10 @@ ppm_load_read_header(FILE *fp,
gchar *retval;
gchar header[MAX_CHARS_IN_ROW];
- /* Check the PPM file Type P2 or P5 */
+ /* Maxval is not used, but value 0 indicates header error. */
+ img->maxval = 0;
+
+ /* Check the PPM file Type P2 or P6 */
retval = fgets (header,MAX_CHARS_IN_ROW,fp);
if (header[0] != ASCII_P ||
@@ -87,14 +91,45 @@ ppm_load_read_header(FILE *fp,
}
/* Get Width and Height */
- img->width = strtol (header,&ptr,0);
- img->height = atoi (ptr);
+ errno = 0;
+ img->width = strtol (header,&ptr,10);
+ if (errno)
+ {
+ g_warning ("Error reading width: %s", strerror(errno));
+ return;
+ }
+ else if (img->width < 0)
+ {
+ g_warning ("Error: width is negative");
+ return;
+ }
+
+ img->height = strtol (ptr,&ptr,10);
+ if (errno)
+ {
+ g_warning ("Error reading height: %s", strerror(errno));
+ return;
+ }
+ else if (img->width < 0)
+ {
+ g_warning ("Error: height is negative");
+ return;
+ }
img->size = img->width * img->height * sizeof (guchar) * CHANNEL_COUNT;
+ /* Ensure it doesn't overflow. */
+ if (!img->width || !img->height ||
+ G_MAXSIZE / img->width / img->height / CHANNEL_COUNT < 1)
+ {
+ g_warning ("Illegal width/height: %ld/%ld", img->width, img->height);
+ return;
+ }
+
retval = fgets (header,100,fp);
+
/* Maxval is not used */
- img->maxval = (int) strtol (header,&ptr,0);
+ img->maxval = (int) strtol (header,&ptr,10);
}
void
@@ -166,12 +201,30 @@ process (GeglOperation *operation,
}
ppm_load_read_header (fp, &img);
- rect.height = img.height;
- rect.width = img.width;
+ if (img.maxval == 0)
+ return FALSE;
+
+ /* Allocating Array Size */
- /* Allocating Array Size */
+ /* Should use g_try_malloc(), but this causes crashes elsewhere because the
+ * error signalled by returning FALSE isn't properly acted upon. Therefore
+ * g_malloc() is used here which aborts if the requested memory size can't be
+ * allocated causing a controlled crash. */
img.data = (guchar*) g_malloc0 (img.size);
+ /* No-op without g_try_malloc(), see above. */
+ if (! img.data)
+ {
+ g_warning ("Couldn't allocate %" G_GSIZE_FORMAT " bytes, giving up.", ((gsize)img.size));
+ /* goto out; */
+ if (stdin != fp)
+ fclose (fp);
+ return FALSE;
+ }
+
+ rect.height = img.height;
+ rect.width = img.width;
+
gegl_buffer_get (output, 1.0, &rect, babl_format ("R'G'B' u8"), img.data,
GEGL_AUTO_ROWSTRIDE);