[gdk-pixbuf] pixdata: Check for RLE pixdata length
- From: Bastien Nocera <hadess src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gdk-pixbuf] pixdata: Check for RLE pixdata length
- Date: Fri, 16 Dec 2016 15:39:05 +0000 (UTC)
commit 10c811117efaa03e1e4d487fc6322c27299f5632
Author: Bastien Nocera <hadess hadess net>
Date: Fri Dec 16 15:17:12 2016 +0100
pixdata: Check for RLE pixdata length
Avoid copying data from past the end of the pixdata when processing
RLE-encoded pixdata.
https://bugzilla.gnome.org/show_bug.cgi?id=775693
gdk-pixbuf/gdk-pixdata.c | 34 ++++++++++++++++++++++++++++++++--
1 files changed, 32 insertions(+), 2 deletions(-)
---
diff --git a/gdk-pixbuf/gdk-pixdata.c b/gdk-pixbuf/gdk-pixdata.c
index b73e5a4..af04244 100644
--- a/gdk-pixbuf/gdk-pixdata.c
+++ b/gdk-pixbuf/gdk-pixdata.c
@@ -412,6 +412,8 @@ gdk_pixdata_from_pixbuf (GdkPixdata *pixdata,
/* From glib's gmem.c */
#define SIZE_OVERFLOWS(a,b) (G_UNLIKELY ((b) > 0 && (a) > G_MAXSIZE / (b)))
+#define RLE_OVERRUN(offset) (rle_buffer_limit == NULL ? FALSE : rle_buffer + (offset) > rle_buffer_limit)
+
/**
* gdk_pixbuf_from_pixdata:
* @pixdata: a #GdkPixdata to convert into a #GdkPixbuf.
@@ -494,13 +496,26 @@ gdk_pixbuf_from_pixdata (const GdkPixdata *pixdata,
if (encoding == GDK_PIXDATA_ENCODING_RLE)
{
const guint8 *rle_buffer = pixdata->pixel_data;
+ guint8 *rle_buffer_limit = NULL;
guint8 *image_buffer = data;
guint8 *image_limit = data + pixdata->rowstride * pixdata->height;
gboolean check_overrun = FALSE;
- while (image_buffer < image_limit)
+ if (pixdata->length >= 1)
+ rle_buffer_limit = pixdata->pixel_data + pixdata->length - GDK_PIXDATA_HEADER_LENGTH;
+
+ while (image_buffer < image_limit &&
+ (rle_buffer_limit != NULL || rle_buffer > rle_buffer_limit))
{
- guint length = *(rle_buffer++);
+ guint length;
+
+ if (RLE_OVERRUN(1))
+ {
+ check_overrun = TRUE;
+ break;
+ }
+
+ length = *(rle_buffer++);
if (length & 128)
{
@@ -508,6 +523,11 @@ gdk_pixbuf_from_pixdata (const GdkPixdata *pixdata,
check_overrun = image_buffer + length * bpp > image_limit;
if (check_overrun)
length = (image_limit - image_buffer) / bpp;
+ if (RLE_OVERRUN(bpp < 4 ? 3 : 4))
+ {
+ check_overrun = TRUE;
+ break;
+ }
if (bpp < 4) /* RGB */
do
{
@@ -522,6 +542,11 @@ gdk_pixbuf_from_pixdata (const GdkPixdata *pixdata,
image_buffer += 4;
}
while (--length);
+ if (RLE_OVERRUN(bpp))
+ {
+ check_overrun = TRUE;
+ break;
+ }
rle_buffer += bpp;
}
else
@@ -530,6 +555,11 @@ gdk_pixbuf_from_pixdata (const GdkPixdata *pixdata,
check_overrun = image_buffer + length > image_limit;
if (check_overrun)
length = image_limit - image_buffer;
+ if (RLE_OVERRUN(length))
+ {
+ check_overrun = TRUE;
+ break;
+ }
memcpy (image_buffer, rle_buffer, length);
image_buffer += length;
rle_buffer += length;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]