Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12-SP2:Update
gdk-pixbuf.7709
gdk-pixbuf-bsc1053417-bmp-updates.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File gdk-pixbuf-bsc1053417-bmp-updates.patch of Package gdk-pixbuf.7709
From bc6bb89a5d3683afd1495f3cde0730bf679c2fed Mon Sep 17 00:00:00 2001 From: Tobias Mueller <muelli@cryptobitch.de> Date: Mon, 28 Nov 2016 16:18:42 +0100 Subject: [PATCH 1/7] bmp: Error out when bottom-to-top BMP is too high BMP files with BITMAPV4HEADER can have negative height when the image is encoded botton-to-top, but when that negative height is INT_MIN, we cannot represent it as a positive integer (|INT_MIN| = INT_MAX + 1). Error out in this case. https://bugzilla.gnome.org/show_bug.cgi?id=775242 --- gdk-pixbuf/io-bmp.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/gdk-pixbuf/io-bmp.c b/gdk-pixbuf/io-bmp.c index 08e3c768c..b896a0349 100644 --- a/gdk-pixbuf/io-bmp.c +++ b/gdk-pixbuf/io-bmp.c @@ -353,6 +353,14 @@ static gboolean DecodeHeader(unsigned char *BFH, unsigned char *BIH, /* Negative heights indicates bottom-down pixelorder */ if (State->Header.height < 0) { + if (State->Header.height == INT_MIN) { + g_set_error_literal (error, + GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_CORRUPT_IMAGE, + _("BMP image has bogus header data")); + State->read_state = READ_STATE_ERROR; + return FALSE; + } State->Header.height = -State->Header.height; State->Header.Negative = 1; } -- 2.14.1 From 41010e949db097f99fc5242492aa7033f7773ddf Mon Sep 17 00:00:00 2001 From: Gokul Krishnan <gk7huki@gmail.com> Date: Wed, 25 May 2016 22:24:00 +0000 Subject: [PATCH 2/7] bmp: Add support for BMP headers with bitmask Header size 52 and 56 failed to load before this patch. https://bugzilla.gnome.org/show_bug.cgi?id=766890 --- gdk-pixbuf/io-bmp.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/gdk-pixbuf/io-bmp.c b/gdk-pixbuf/io-bmp.c index b896a0349..f78c092b6 100644 --- a/gdk-pixbuf/io-bmp.c +++ b/gdk-pixbuf/io-bmp.c @@ -298,6 +298,18 @@ static gboolean DecodeHeader(unsigned char *BFH, unsigned char *BIH, State->Header.height = lsb_32 (&BIH[8]); State->Header.depth = lsb_16 (&BIH[14]); State->Compressed = lsb_32 (&BIH[16]); + } else if (State->Header.size == 56) { + /* BMP v3 with RGBA bitmasks */ + State->Header.width = lsb_32 (&BIH[4]); + State->Header.height = lsb_32 (&BIH[8]); + State->Header.depth = lsb_16 (&BIH[14]); + State->Compressed = lsb_32 (&BIH[16]); + } else if (State->Header.size == 52) { + /* BMP v3 with RGB bitmasks */ + State->Header.width = lsb_32 (&BIH[4]); + State->Header.height = lsb_32 (&BIH[8]); + State->Header.depth = lsb_16 (&BIH[14]); + State->Compressed = lsb_32 (&BIH[16]); } else if (State->Header.size == 40) { /* BMP v3 */ State->Header.width = lsb_32 (&BIH[4]); @@ -495,9 +507,10 @@ static gboolean DecodeHeader(unsigned char *BFH, unsigned char *BIH, State->BufferSize = State->LineWidth; } } else if (State->Compressed == BI_BITFIELDS) { - if (State->Header.size == 108 || State->Header.size == 124) + if (State->Header.size == 52 || State->Header.size == 56 || + State->Header.size == 108 || State->Header.size == 124) { - /* v4 and v5 have the bitmasks in the header */ + /* extended v3, v4 and v5 have the bitmasks in the header */ if (!decode_bitmasks (&BIH[40], State, error)) { State->read_state = READ_STATE_ERROR; return FALSE; @@ -607,8 +620,8 @@ decode_bitmasks (guchar *buf, find_bits (State->g_mask, &State->g_shift, &State->g_bits); find_bits (State->b_mask, &State->b_shift, &State->b_bits); - /* v4 and v5 have an alpha mask */ - if (State->Header.size == 108 || State->Header.size == 124) { + /* extended v3, v4 and v5 have an alpha mask */ + if (State->Header.size == 56 || State->Header.size == 108 || State->Header.size == 124) { buf += 4; State->a_mask = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); find_bits (State->a_mask, &State->a_shift, &State->a_bits); -- 2.14.1 From 111dbb30db97e07c8435b58ea15093bea57c9f1c Mon Sep 17 00:00:00 2001 From: Philip Withnall <withnall@endlessm.com> Date: Mon, 16 Jan 2017 10:14:49 +0000 Subject: [PATCH 3/7] io-bmp: Add overflow checks to BMP image saver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Return an error if the image width or height are too big to fit in the BMP size fields. This bumps our GLib dependency to 2.48.0, as it uses g_uint_checked_mul(). If you want to backport this fix, it’s probably best to use __builtin_umul_overflow() directly (if compiling using GCC or another compiler which supports it). Coverity ID: 1388532 https://bugzilla.gnome.org/show_bug.cgi?id=777315 --- gdk-pixbuf/io-bmp.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/gdk-pixbuf/io-bmp.c b/gdk-pixbuf/io-bmp.c index f78c092b6..6460e7f1b 100644 --- a/gdk-pixbuf/io-bmp.c +++ b/gdk-pixbuf/io-bmp.c @@ -1327,6 +1327,7 @@ gdk_pixbuf__bmp_image_save_to_callback (GdkPixbufSaveFunc save_func, GError **error) { guint width, height, channel, size, stride, src_stride, x, y; + guint bf_size; guchar BFH_BIH[54], *pixels, *buf, *src, *dst, *dst_line; gboolean ret; @@ -1335,14 +1336,33 @@ gdk_pixbuf__bmp_image_save_to_callback (GdkPixbufSaveFunc save_func, channel = gdk_pixbuf_get_n_channels (pixbuf); pixels = gdk_pixbuf_get_pixels (pixbuf); src_stride = gdk_pixbuf_get_rowstride (pixbuf); - stride = (width * 3 + 3) & ~3; - size = stride * height; + + /* stride = (width * 3 + 3) & ~3 */ + if (!g_uint_checked_mul (&stride, width, 3) || + !g_uint_checked_add (&stride, stride, 3)) { + g_set_error_literal (error, GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_FAILED, + _("Image is too wide for BMP format.")); + return FALSE; + } + + stride &= ~3; + + /* size = stride * height + * bf_size = size + 14 + 40 */ + if (!g_uint_checked_mul (&size, stride, height) || + !g_uint_checked_add (&bf_size, size, 14 + 40)) { + g_set_error_literal (error, GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_FAILED, + _("Image is too wide for BMP format.")); + return FALSE; + } /* filling BFH */ dst = BFH_BIH; *dst++ = 'B'; /* bfType */ *dst++ = 'M'; - put32 (dst, size + 14 + 40); /* bfSize */ + put32 (dst, bf_size); /* bfSize */ put32 (dst, 0); /* bfReserved1 + bfReserved2 */ put32 (dst, 14 + 40); /* bfOffBits */ -- 2.14.1 From ff61b892e87e77ad339c09978d792bd713f4ac3b Mon Sep 17 00:00:00 2001 From: Bastien Nocera <hadess@hadess.net> Date: Thu, 13 Jul 2017 18:53:26 +0200 Subject: [PATCH 4/7] loaders: Remove "error && *error == NULL" checks g_set_error() and friends already do those checks. --- gdk-pixbuf/io-bmp.c | 10 ++++------ gdk-pixbuf/io-jpeg.c | 26 +++++++++++--------------- gdk-pixbuf/io-png.c | 51 ++++++++++++++++++++------------------------------- 3 files changed, 35 insertions(+), 52 deletions(-) diff --git a/gdk-pixbuf/io-bmp.c b/gdk-pixbuf/io-bmp.c index 6460e7f1b..9ba359750 100644 --- a/gdk-pixbuf/io-bmp.c +++ b/gdk-pixbuf/io-bmp.c @@ -746,12 +746,10 @@ static gboolean gdk_pixbuf__bmp_image_stop_load(gpointer data, GError **error) g_object_unref(context->pixbuf); if (context->read_state == READ_STATE_HEADERS) { - if (error && *error == NULL) { - g_set_error_literal (error, - GDK_PIXBUF_ERROR, - GDK_PIXBUF_ERROR_CORRUPT_IMAGE, - _("Premature end-of-file encountered")); - } + g_set_error_literal (error, + GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_CORRUPT_IMAGE, + _("Premature end-of-file encountered")); retval = FALSE; } diff --git a/gdk-pixbuf/io-jpeg.c b/gdk-pixbuf/io-jpeg.c index ee5d321ae..c88ac462d 100644 --- a/gdk-pixbuf/io-jpeg.c +++ b/gdk-pixbuf/io-jpeg.c @@ -662,14 +662,12 @@ gdk_pixbuf__jpeg_image_load (FILE *f, GError **error) default: g_object_unref (pixbuf); pixbuf = NULL; - if (error && *error == NULL) { - g_set_error (error, - GDK_PIXBUF_ERROR, - GDK_PIXBUF_ERROR_UNKNOWN_TYPE, - _("Unsupported JPEG color space (%s)"), - colorspace_name (cinfo.out_color_space)); - } - goto out; + g_set_error (error, + GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_UNKNOWN_TYPE, + _("Unsupported JPEG color space (%s)"), + colorspace_name (cinfo.out_color_space)); + goto out; } } @@ -875,13 +873,11 @@ gdk_pixbuf__jpeg_image_load_lines (JpegProgContext *context, convert_cmyk_to_rgb (cinfo, lines); break; default: - if (error && *error == NULL) { - g_set_error (error, - GDK_PIXBUF_ERROR, - GDK_PIXBUF_ERROR_UNKNOWN_TYPE, - _("Unsupported JPEG color space (%s)"), - colorspace_name (cinfo->out_color_space)); - } + g_set_error (error, + GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_UNKNOWN_TYPE, + _("Unsupported JPEG color space (%s)"), + colorspace_name (cinfo->out_color_space)); return FALSE; } diff --git a/gdk-pixbuf/io-png.c b/gdk-pixbuf/io-png.c index e5ab22bcb..9af7a2c7a 100644 --- a/gdk-pixbuf/io-png.c +++ b/gdk-pixbuf/io-png.c @@ -313,13 +313,10 @@ gdk_pixbuf__png_image_load (FILE *f, GError **error) pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, ctype & PNG_COLOR_MASK_ALPHA, 8, w, h); if (!pixbuf) { - if (error && *error == NULL) { - g_set_error_literal (error, - GDK_PIXBUF_ERROR, - GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, - _("Insufficient memory to load PNG file")); - } - + g_set_error_literal (error, + GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, + _("Insufficient memory to load PNG file")); png_destroy_read_struct (&png_ptr, &info_ptr, NULL); return NULL; @@ -525,11 +522,9 @@ gdk_pixbuf__png_image_stop_load (gpointer context, GError **error) if (lc->pixbuf) g_object_unref (lc->pixbuf); else { - if (error && *error == NULL) { - g_set_error_literal (error, GDK_PIXBUF_ERROR, - GDK_PIXBUF_ERROR_CORRUPT_IMAGE, - _("Premature end-of-file encountered")); - } + g_set_error_literal (error, GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_CORRUPT_IMAGE, + _("Premature end-of-file encountered")); retval = FALSE; } @@ -664,12 +659,10 @@ png_info_callback (png_structp png_read_ptr, if (w == 0 || h == 0) { lc->fatal_error_occurred = TRUE; - if (lc->error && *lc->error == NULL) { - g_set_error_literal (lc->error, - GDK_PIXBUF_ERROR, - GDK_PIXBUF_ERROR_FAILED, - _("Transformed PNG has zero width or height.")); - } + g_set_error_literal (lc->error, + GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_FAILED, + _("Transformed PNG has zero width or height.")); return; } } @@ -679,13 +672,11 @@ png_info_callback (png_structp png_read_ptr, if (lc->pixbuf == NULL) { /* Failed to allocate memory */ lc->fatal_error_occurred = TRUE; - if (lc->error && *lc->error == NULL) { - g_set_error (lc->error, - GDK_PIXBUF_ERROR, - GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, - _("Insufficient memory to store a %lu by %lu image; try exiting some applications to reduce memory usage"), - (gulong) width, (gulong) height); - } + g_set_error (lc->error, + GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, + _("Insufficient memory to store a %lu by %lu image; try exiting some applications to reduce memory usage"), + (gulong) width, (gulong) height); return; } @@ -755,12 +746,10 @@ png_row_callback (png_structp png_read_ptr, if (row_num >= lc->pixbuf->height) { lc->fatal_error_occurred = TRUE; - if (lc->error && *lc->error == NULL) { - g_set_error_literal (lc->error, - GDK_PIXBUF_ERROR, - GDK_PIXBUF_ERROR_CORRUPT_IMAGE, - _("Fatal error reading PNG image file")); - } + g_set_error_literal (lc->error, + GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_CORRUPT_IMAGE, + _("Fatal error reading PNG image file")); return; } -- 2.14.1 From 43650722f6facc77e59329cf4f9012a4f8f8fab4 Mon Sep 17 00:00:00 2001 From: Bastien Nocera <hadess@hadess.net> Date: Thu, 13 Jul 2017 19:41:06 +0200 Subject: [PATCH 5/7] bmp: Prevent multiplication overflow in DecodeHeader The multiplication can overflow as UBSan complained: io-bmp.c:475:63: runtime error: signed integer overflow: 524672 * 4096 cannot be represented in type 'int' Fix this by checking the header dimensions for sanity, and then checking whether the rowstride * height multiplication does not overflow and fits within the range. https://bugzilla.gnome.org/show_bug.cgi?id=776694 --- gdk-pixbuf/io-bmp.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/gdk-pixbuf/io-bmp.c b/gdk-pixbuf/io-bmp.c index 9ba359750..e8605058a 100644 --- a/gdk-pixbuf/io-bmp.c +++ b/gdk-pixbuf/io-bmp.c @@ -432,6 +432,8 @@ static gboolean DecodeHeader(unsigned char *BFH, unsigned char *BIH, State->LineWidth = (State->LineWidth / 4) * 4 + 4; if (State->pixbuf == NULL) { + guint64 len; + if (State->size_func) { gint width = State->Header.width; gint height = State->Header.height; @@ -444,6 +446,19 @@ static gboolean DecodeHeader(unsigned char *BFH, unsigned char *BIH, } } + /* rowstride is always >= width, so do an early check for bogus header */ + if (State->Header.width <= 0 || + State->Header.height <= 0 || + !g_uint64_checked_mul (&len, State->Header.width, State->Header.height) || + len > G_MAXINT) { + g_set_error_literal (error, + GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_CORRUPT_IMAGE, + _("BMP image has bogus header data")); + State->read_state = READ_STATE_ERROR; + return FALSE; + } + if (State->Type == 32 || State->Compressed == BI_RLE4 || State->Compressed == BI_RLE8) @@ -456,7 +471,17 @@ static gboolean DecodeHeader(unsigned char *BFH, unsigned char *BIH, gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, (gint) State->Header.width, (gint) State->Header.height); - + + if (!g_uint64_checked_mul (&len, State->pixbuf->rowstride, State->Header.height) || + len > G_MAXINT) { + g_set_error_literal (error, + GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_CORRUPT_IMAGE, + _("BMP image has bogus header data")); + State->read_state = READ_STATE_ERROR; + return FALSE; + } + if (State->pixbuf == NULL) { g_set_error_literal (error, GDK_PIXBUF_ERROR, -- 2.14.1 From 2cf6b3f01d12618679dab62b58f0bb86d08d74c5 Mon Sep 17 00:00:00 2001 From: Bastien Nocera <hadess@hadess.net> Date: Wed, 26 Jul 2017 16:33:40 +0200 Subject: [PATCH 6/7] bmp: Tighten image dimension checks The rowstride *could* be negative if the pixbuf is invalid. Check that it is valid before using it to sanity check the image's dimensions. See https://bugzilla.gnome.org/show_bug.cgi?id=776694 --- gdk-pixbuf/io-bmp.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/gdk-pixbuf/io-bmp.c b/gdk-pixbuf/io-bmp.c index e8605058a..e8ccce446 100644 --- a/gdk-pixbuf/io-bmp.c +++ b/gdk-pixbuf/io-bmp.c @@ -433,6 +433,7 @@ static gboolean DecodeHeader(unsigned char *BFH, unsigned char *BIH, if (State->pixbuf == NULL) { guint64 len; + int rowstride; if (State->size_func) { gint width = State->Header.width; @@ -472,7 +473,9 @@ static gboolean DecodeHeader(unsigned char *BFH, unsigned char *BIH, (gint) State->Header.width, (gint) State->Header.height); - if (!g_uint64_checked_mul (&len, State->pixbuf->rowstride, State->Header.height) || + rowstride = gdk_pixbuf_get_rowstride (State->pixbuf); + if (rowstride <= 0 || + !g_uint64_checked_mul (&len, rowstride, State->Header.height) || len > G_MAXINT) { g_set_error_literal (error, GDK_PIXBUF_ERROR, -- 2.14.1 From b5f42b3f3b41a0a57974345b8780a339d012cb47 Mon Sep 17 00:00:00 2001 From: Bastien Nocera <hadess@hadess.net> Date: Wed, 26 Jul 2017 17:07:08 +0200 Subject: [PATCH 7/7] bmp: Avoid allocating large buffers when not needed Avoid allocating nearly 6 gigs of data when parsing the CVE-2015-4491 test only to free it when we've calculated that the rowstride * height would overflow by calculating the rowstride before doing the allocation, using the new gdk_pixbuf_calculate_rowstride() helper. https://bugzilla.gnome.org/show_bug.cgi?id=765094 --- gdk-pixbuf/io-bmp.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/gdk-pixbuf/io-bmp.c b/gdk-pixbuf/io-bmp.c index e8ccce446..06b0cff2c 100644 --- a/gdk-pixbuf/io-bmp.c +++ b/gdk-pixbuf/io-bmp.c @@ -434,6 +434,7 @@ static gboolean DecodeHeader(unsigned char *BFH, unsigned char *BIH, if (State->pixbuf == NULL) { guint64 len; int rowstride; + gboolean has_alpha; if (State->size_func) { gint width = State->Header.width; @@ -460,20 +461,17 @@ static gboolean DecodeHeader(unsigned char *BFH, unsigned char *BIH, return FALSE; } - if (State->Type == 32 || - State->Compressed == BI_RLE4 || + if (State->Type == 32 || + State->Compressed == BI_RLE4 || State->Compressed == BI_RLE8) - State->pixbuf = - gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, - (gint) State->Header.width, - (gint) State->Header.height); + has_alpha = TRUE; else - State->pixbuf = - gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, - (gint) State->Header.width, - (gint) State->Header.height); + has_alpha = FALSE; + + rowstride = gdk_pixbuf_calculate_rowstride (GDK_COLORSPACE_RGB, has_alpha, 8, + (gint) State->Header.width, + (gint) State->Header.height); - rowstride = gdk_pixbuf_get_rowstride (State->pixbuf); if (rowstride <= 0 || !g_uint64_checked_mul (&len, rowstride, State->Header.height) || len > G_MAXINT) { @@ -485,6 +483,10 @@ static gboolean DecodeHeader(unsigned char *BFH, unsigned char *BIH, return FALSE; } + State->pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, has_alpha, 8, + (gint) State->Header.width, + (gint) State->Header.height); + if (State->pixbuf == NULL) { g_set_error_literal (error, GDK_PIXBUF_ERROR, @@ -492,8 +494,8 @@ static gboolean DecodeHeader(unsigned char *BFH, unsigned char *BIH, _("Not enough memory to load bitmap image")); State->read_state = READ_STATE_ERROR; return FALSE; - } - + } + if (State->prepared_func != NULL) /* Notify the client that we are ready to go */ (*State->prepared_func) (State->pixbuf, NULL, State->user_data); -- 2.14.1
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor