Accepting request 424115 from home:zhangxiaofei:branches:GNOME:Factory

- Add fixes for some crashes, taken from upstream git (bsc#988745
  bsc#991450 CVE-2016-6352):
  gdk-pixbuf-bgo768688-bmp-overflow.patch
  gdk-pixbuf-bgo768484-ico-set-errors.patch
  gdk-pixbuf-bgo769738-bmp-overflow.patch
  gdk-pixbuf-bgo769170-ico-headers.patch

OBS-URL: https://build.opensuse.org/request/show/424115
OBS-URL: https://build.opensuse.org/package/show/GNOME:Factory/gdk-pixbuf?expand=0&rev=111
This commit is contained in:
Bjørn Lie 2016-09-01 09:33:46 +00:00 committed by Git OBS Bridge
parent d18b77eb0c
commit 7eea91dac6
6 changed files with 400 additions and 0 deletions

View File

@ -0,0 +1,52 @@
From 0cff83e985fba5350695c00ed1ac30fc31ec5960 Mon Sep 17 00:00:00 2001
From: Hanno Boeck <hanno@hboeck.de>
Date: Wed, 6 Jul 2016 13:05:00 +0000
Subject: [PATCH] ico: Always set errors
When the ico header turn out to be bad, always set an
error when we fail. Otherwise, applications will get
confused.
This commit also adds an example image with a bad ico header.
https://bugzilla.gnome.org/show_bug.cgi?id=768484
---
gdk-pixbuf/io-ico.c | 14 ++++++++++++--
tests/test-images/randomly-modified/bad-header.ico | Bin 0 -> 6 bytes
2 files changed, 12 insertions(+), 2 deletions(-)
create mode 100644 tests/test-images/randomly-modified/bad-header.ico
diff --git a/gdk-pixbuf/io-ico.c b/gdk-pixbuf/io-ico.c
index 86714af..82d3e4e 100644
--- a/gdk-pixbuf/io-ico.c
+++ b/gdk-pixbuf/io-ico.c
@@ -258,8 +258,13 @@ static void DecodeHeader(guchar *Data, gint Bytes,
State->HeaderBuf = tmp;
State->BytesInHeaderBuf = State->HeaderSize;
}
- if (Bytes < State->HeaderSize)
+ if (Bytes < State->HeaderSize) {
+ g_set_error_literal (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("Not enough bytes for header"));
return;
+ }
/* Now iterate through the ICONDIRENTRY structures, and sort them by
* which one we think is "best" (essentially the largest) */
@@ -399,8 +404,13 @@ static void DecodeHeader(guchar *Data, gint Bytes,
State->HeaderBuf = tmp;
State->BytesInHeaderBuf = State->HeaderSize;
}
- if (Bytes < State->HeaderSize)
+ if (Bytes < State->HeaderSize) {
+ g_set_error_literal (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("Not enough bytes for header"));
return;
+ }
/* Negative heights mean top-down pixel-order */
if (State->Header.height < 0) {

View File

@ -0,0 +1,56 @@
From b69009f2a2de151103ed87e9594615ba0fe72daf Mon Sep 17 00:00:00 2001
From: Tobias Mueller <gnome-bugs@muelli.cryptobitch.de>
Date: Mon, 11 Jul 2016 17:01:00 +0000
Subject: [PATCH] bmp: Fix an integer overflow in DecodeColormap
Return an error if n_colors * samples overflows.
This commit also adds a reproducer that will cause
pixbuf-randomly-modified to crash in the absence of
the patch.
https://bugzilla.gnome.org/show_bug.cgi?id=768688
---
gdk-pixbuf/io-bmp.c | 15 ++++++++++++---
tests/test-images/randomly-modified/decodecolormap.bmp | Bin 0 -> 118 bytes
2 files changed, 12 insertions(+), 3 deletions(-)
create mode 100644 tests/test-images/randomly-modified/decodecolormap.bmp
diff --git a/gdk-pixbuf/io-bmp.c b/gdk-pixbuf/io-bmp.c
index f412997..748ebae 100644
--- a/gdk-pixbuf/io-bmp.c
+++ b/gdk-pixbuf/io-bmp.c
@@ -518,12 +518,16 @@ static gboolean DecodeColormap (guchar *buff,
{
gint i;
gint samples;
+ guint newbuffersize;
g_assert (State->read_state == READ_STATE_PALETTE);
samples = (State->Header.size == 12 ? 3 : 4);
- if (State->BufferSize < State->Header.n_colors * samples) {
- State->BufferSize = State->Header.n_colors * samples;
+ newbuffersize = State->Header.n_colors * samples;
+ if (newbuffersize / samples != State->Header.n_colors) /* Integer overflow check */
+ return FALSE;
+ if (State->BufferSize < newbuffersize) {
+ State->BufferSize = newbuffersize;
if (!grow_buffer (State, error))
return FALSE;
return TRUE;
@@ -1247,8 +1251,13 @@ gdk_pixbuf__bmp_image_load_increment(gpointer data,
break;
case READ_STATE_PALETTE:
- if (!DecodeColormap (context->buff, context, error))
+ if (!DecodeColormap (context->buff, context, error)) {
+ g_set_error (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("Error while decoding colormap"));
return FALSE;
+ }
break;
case READ_STATE_BITMASKS:

View File

@ -0,0 +1,213 @@
From 88af50a864195da1a4f7bda5f02539704fbda599 Mon Sep 17 00:00:00 2001
From: Matthias Clasen <mclasen@redhat.com>
Date: Wed, 3 Aug 2016 12:40:48 -0400
Subject: [PATCH] ico: Be more careful when parsing headers
There is some redundancy between the ico directory and the
bitmap image header. If the two disagree on the icon dimensions,
just toss the image, instead of risking crashes or OOM later. Also
add some more debug spew that helped in tracking this down, and
make error messages more unique.
The commit also includes a test image that has an example of
this discrepancy and triggers the early exit.
https://bugzilla.gnome.org/show_bug.cgi?id=769170
Backported by Mike Gorse <mgorse@suse.com>
---
diff -urp gdk-pixbuf-2.34.0.orig/gdk-pixbuf/io-ico.c gdk-pixbuf-2.34.0/gdk-pixbuf/io-ico.c
--- gdk-pixbuf-2.34.0.orig/gdk-pixbuf/io-ico.c 2016-08-30 13:57:44.715146613 -0500
+++ gdk-pixbuf-2.34.0/gdk-pixbuf/io-ico.c 2016-08-30 15:17:40.887044723 -0500
@@ -23,6 +23,8 @@
*/
#undef DUMPBIH
+#define DEBUG(s)
+
/*
Icons are just like BMP's, except for the header.
@@ -75,14 +77,14 @@ struct BitmapInfoHeader {
};
#ifdef DUMPBIH
-/*
+/*
DumpBIH printf's the values in a BitmapInfoHeader to the screen, for
debugging purposes.
*/
static void DumpBIH(unsigned char *BIH)
-{
+{
printf("biSize = %i \n",
(int)(BIH[3] << 24) + (BIH[2] << 16) + (BIH[1] << 8) + (BIH[0]));
printf("biWidth = %i \n",
@@ -125,6 +127,8 @@ struct headerpair {
/* Score the various parts of the icon */
struct ico_direntry_data {
gint ImageScore;
+ gint width;
+ gint height;
gint DIBoffset;
gint x_hot;
gint y_hot;
@@ -241,11 +245,12 @@ static void DecodeHeader(guchar *Data, g
return;
}
-
IconCount = (Data[5] << 8) + (Data[4]);
State->HeaderSize = 6 + IconCount*16;
+ DEBUG(g_print ("Image type: %d (%s)\nImage count: %d\n", imgtype, imgtype == 2 ? "cursor" : "icon", IconCount));
+
if (State->HeaderSize>State->BytesInHeaderBuf) {
guchar *tmp=g_try_realloc(State->HeaderBuf,State->HeaderSize);
if (!tmp) {
@@ -259,10 +264,6 @@ static void DecodeHeader(guchar *Data, g
State->BytesInHeaderBuf = State->HeaderSize;
}
if (Bytes < State->HeaderSize) {
- g_set_error_literal (error,
- GDK_PIXBUF_ERROR,
- GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
- _("Not enough bytes for header"));
return;
}
@@ -272,17 +273,37 @@ static void DecodeHeader(guchar *Data, g
State->entries = 0;
Ptr = Data + 6;
for (I=0;I<IconCount;I++) {
+ int width;
+ int height;
+ int x_hot;
+ int y_hot;
+ int data_size;
+ int data_offset;
+
+ width = Ptr[0];
+ height = Ptr[1];
+ x_hot = (Ptr[5] << 8) + Ptr[4];
+ y_hot = (Ptr[7] << 8) + Ptr[6];
+ data_size = (Ptr[11] << 24) + (Ptr[10] << 16) + (Ptr[9] << 8) + (Ptr[8]);
+ data_offset = (Ptr[15] << 24) + (Ptr[14] << 16) + (Ptr[13] << 8) + (Ptr[12]);
+ DEBUG(g_print ("Image %d: %d x %d\n\tPalette: %d\n", I, width, height, {tr[2]);
+ if (imgtype == 2)
+ g_print ("\tHotspot: %d x %d\n", x_hot, y_hot);
+ else
+ g_print ("\tColor planes: %d\n\tBits per pixel: %d\n", x_hot, y_hot);
+ g_print ("\tSize: %d\n\tOffset: %d\n", data_size, data_offset);)
+
entry = g_new0 (struct ico_direntry_data, 1);
- entry->ImageScore = (Ptr[11] << 24) + (Ptr[10] << 16) + (Ptr[9] << 8) + (Ptr[8]);
- if (entry->ImageScore == 0)
- entry->ImageScore = 256;
- entry->x_hot = (Ptr[5] << 8) + Ptr[4];
- entry->y_hot = (Ptr[7] << 8) + Ptr[6];
- entry->DIBoffset = (Ptr[15]<<24)+(Ptr[14]<<16)+
- (Ptr[13]<<8) + (Ptr[12]);
+ entry->ImageScore = data_size;
+
+ entry->width = width ? width : 256;
+ entry->height = height ? height : 256;
+ entry->x_hot = x_hot;
+ entry->y_hot = y_hot;
+ entry->DIBoffset = data_offset;
State->entries = g_list_insert_sorted (State->entries, entry, compare_direntry_scores);
Ptr += 16;
- }
+ }
/* Now go through and find one we can parse */
entry = NULL;
@@ -351,9 +372,9 @@ static void DecodeHeader(guchar *Data, g
#ifdef DUMPBIH
DumpBIH(BIH);
-#endif
+#endif
/* Add the palette to the headersize */
-
+
State->Header.width =
(int)(BIH[7] << 24) + (BIH[6] << 16) + (BIH[5] << 8) + (BIH[4]);
if (State->Header.width == 0)
@@ -364,12 +385,28 @@ static void DecodeHeader(guchar *Data, g
/* /2 because the BIH height includes the transparency mask */
if (State->Header.height == 0)
State->Header.height = 256;
+
+ /* Negative heights mean top-down pixel-order */
+ if (State->Header.height < 0) {
+ State->Header.height = -State->Header.height;
+ State->Header.Negative = 1;
+ }
+ if (State->Header.width < 0) {
+ State->Header.width = -State->Header.width;
+ }
+
+ if (State->Header.width != entry->width ||
+ State->Header.height != entry->height) {
+ g_set_error_literal (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("Invalid header in icon"));
+ return;
+ }
+
State->Header.depth = (BIH[15] << 8) + (BIH[14]);
+ State->Type = State->Header.depth;
- State->Type = State->Header.depth;
- if (State->Lines>=State->Header.height)
- State->Type = 1; /* The transparency mask is 1 bpp */
-
/* Determine the palette size. If the header indicates 0, it
is actually the maximum for the bpp. You have to love the
guys who made the spec. */
@@ -405,24 +442,9 @@ static void DecodeHeader(guchar *Data, g
State->BytesInHeaderBuf = State->HeaderSize;
}
if (Bytes < State->HeaderSize) {
- g_set_error_literal (error,
- GDK_PIXBUF_ERROR,
- GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
- _("Not enough bytes for header"));
return;
}
- /* Negative heights mean top-down pixel-order */
- if (State->Header.height < 0) {
- State->Header.height = -State->Header.height;
- State->Header.Negative = 1;
- }
- if (State->Header.width < 0) {
- State->Header.width = -State->Header.width;
- }
- g_assert (State->Header.width > 0);
- g_assert (State->Header.height > 0);
-
if (State->Type == 32)
State->LineWidth = State->Header.width * 4;
else if (State->Type == 24)
@@ -465,7 +487,6 @@ static void DecodeHeader(guchar *Data, g
if (State->pixbuf == NULL) {
-#if 1
if (State->size_func) {
gint width = State->Header.width;
gint height = State->Header.height;
@@ -476,7 +497,6 @@ static void DecodeHeader(guchar *Data, g
return;
}
}
-#endif
State->pixbuf =
gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8,

View File

@ -0,0 +1,57 @@
From 779429ce34e439c01d257444fe9d6739e72a2024 Mon Sep 17 00:00:00 2001
From: Tobias Mueller <gnome-bugs@muelli.cryptobitch.de>
Date: Tue, 12 Jul 2016 15:20:00 +0000
Subject: [PATCH] bmp: Detect integer overflow of the line width
Instead of risking crashes or OOM, return an error if
we detect integer overflow.
The commit also includes a test image that triggers
this overflow when used with pixbuf-read.
https://bugzilla.gnome.org/show_bug.cgi?id=768738
---
gdk-pixbuf/io-bmp.c | 21 ++++++++++++---------
.../randomly-modified/bmp-line-overflow.bmp | Bin 0 -> 74 bytes
2 files changed, 12 insertions(+), 9 deletions(-)
create mode 100644 tests/test-images/randomly-modified/bmp-line-overflow.bmp
diff --git a/gdk-pixbuf/io-bmp.c b/gdk-pixbuf/io-bmp.c
index 748ebae..08e3c76 100644
--- a/gdk-pixbuf/io-bmp.c
+++ b/gdk-pixbuf/io-bmp.c
@@ -254,6 +254,7 @@ static gboolean DecodeHeader(unsigned char *BFH, unsigned char *BIH,
GError **error)
{
gint clrUsed;
+ guint bytesPerPixel;
/* First check for the two first bytes content. A sane
BMP file must start with bytes 0x42 0x4D. */
@@ -380,15 +381,17 @@ static gboolean DecodeHeader(unsigned char *BFH, unsigned char *BIH,
return FALSE;
}
- if (State->Type == 32)
- State->LineWidth = State->Header.width * 4;
- else if (State->Type == 24)
- State->LineWidth = State->Header.width * 3;
- else if (State->Type == 16)
- State->LineWidth = State->Header.width * 2;
- else if (State->Type == 8)
- State->LineWidth = State->Header.width * 1;
- else if (State->Type == 4)
+ if ((State->Type >= 8) && (State->Type <= 32) && (State->Type % 8 == 0)) {
+ bytesPerPixel = State->Type / 8;
+ State->LineWidth = State->Header.width * bytesPerPixel;
+ if (State->Header.width != State->LineWidth / bytesPerPixel) {
+ g_set_error_literal (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("BMP image width too large"));
+ return FALSE;
+ }
+ } else if (State->Type == 4)
State->LineWidth = (State->Header.width + 1) / 2;
else if (State->Type == 1) {
State->LineWidth = State->Header.width / 8;

View File

@ -1,3 +1,13 @@
-------------------------------------------------------------------
Tue Aug 30 18:39:06 UTC 2016 - mgorse@suse.com
- Add fixes for some crashes, taken from upstream git (bsc#988745
bsc#991450 CVE-2016-6352):
gdk-pixbuf-bgo768688-bmp-overflow.patch
gdk-pixbuf-bgo768484-ico-set-errors.patch
gdk-pixbuf-bgo769738-bmp-overflow.patch
gdk-pixbuf-bgo769170-ico-headers.patch
-------------------------------------------------------------------
Wed Apr 13 10:35:15 UTC 2016 - idonmez@suse.com

View File

@ -30,6 +30,14 @@ Source: http://download.gnome.org/sources/gdk-pixbuf/2.34/%{name}-%{vers
Source1: macros.gdk-pixbuf
Source2: README.SUSE
Source99: baselibs.conf
# PATCH-FIX-UPSTREAM gdk-pixbuf-bgo768688-bmp-overflow.patch bgo#768688 mgorse@suse.com -- fix a bmp overflow.
Patch0: gdk-pixbuf-bgo768688-bmp-overflow.patch
# PATCh-FIX-UPSTREAM gdk-pixbuf-bgo768484-ico-set-errors.patch bgo#768484 mgorse@suse.com -- ico: always set errors.
Patch1: gdk-pixbuf-bgo768484-ico-set-errors.patch
# PATCH-FIX-UPSTREAM gdk-pixbuf-bgo769738-bmp-overflow.patch bsc#988745 bgo#769738 mgorse@suse.com -- fix another bmp overflow.
Patch2: gdk-pixbuf-bgo769738-bmp-overflow.patch
# PATCh-FIX-UPSTREAM gdk-pixbuf-bgo769170-ico-headers.patch bsc#991450 bgo#769170 CVE-2016-6352 mgorse@suse.com -- be more careful when parsing ico headers.
Patch3: gdk-pixbuf-bgo769170-ico-headers.patch
BuildRequires: libjasper-devel
BuildRequires: libjpeg-devel
BuildRequires: libtiff-devel
@ -98,6 +106,10 @@ This package contains development files for gdk-pixbuf.
%prep
%setup -q
translation-update-upstream
%patch0 -p1
%patch1 -p1
%patch2 -p1
%patch3 -p1
%if "%_lib" == "lib64"
cp -a %{S:2} .
%endif