From 2663fccc4235eab4b455fce48c3e3b0073e838e0 Mon Sep 17 00:00:00 2001 From: Adrian Vovk Date: Wed, 26 Aug 2026 15:57:11 -0400 Subject: [PATCH] ico: Protect against out-of-bounds palette index We previously didn't check that the palette indices in the pixel data referred to palette colors that actually exist. A malformed ICO file could thus trick gdk-pixbuf into reading past the end of the palette data and leaking heap memory. Closes: #302 Fixes: CVE-2026-16768 --- gdk-pixbuf/io-ico.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/gdk-pixbuf/io-ico.c b/gdk-pixbuf/io-ico.c index 2523c0803..21008307f 100644 --- a/gdk-pixbuf/io-ico.c +++ b/gdk-pixbuf/io-ico.c @@ -725,6 +725,7 @@ static void OneLine8(struct ico_progressive_state *context) gint X; guchar *Pixels; gsize rowstride = gdk_pixbuf_get_rowstride (context->pixbuf); + gint palette_size = (context->HeaderSize - INFOHEADER_SIZE - context->DIBoffset) / 4; X = 0; if (context->Header.Negative == 0) @@ -734,13 +735,17 @@ static void OneLine8(struct ico_progressive_state *context) Pixels = (gdk_pixbuf_get_pixels (context->pixbuf) + rowstride * context->Lines); while (X < context->Header.width) { + guint8 idx = context->LineBuf[X]; + if (idx >= palette_size) + idx = 0; + /* The joys of having a BGR byteorder */ Pixels[X * 4 + 0] = - context->HeaderBuf[4 * context->LineBuf[X] + INFOHEADER_SIZE + 2 + context->DIBoffset]; + context->HeaderBuf[4 * idx + INFOHEADER_SIZE + 2 + context->DIBoffset]; Pixels[X * 4 + 1] = - context->HeaderBuf[4 * context->LineBuf[X] + INFOHEADER_SIZE + 1 +context->DIBoffset]; + context->HeaderBuf[4 * idx + INFOHEADER_SIZE + 1 +context->DIBoffset]; Pixels[X * 4 + 2] = - context->HeaderBuf[4 * context->LineBuf[X] + INFOHEADER_SIZE +context->DIBoffset]; + context->HeaderBuf[4 * idx + INFOHEADER_SIZE +context->DIBoffset]; Pixels[X * 4 + 3] = 0xff; X++; } @@ -750,6 +755,7 @@ static void OneLine4(struct ico_progressive_state *context) gint X; guchar *Pixels; gsize rowstride = gdk_pixbuf_get_rowstride (context->pixbuf); + gint palette_size = (context->HeaderSize - INFOHEADER_SIZE - context->DIBoffset) / 4; X = 0; if (context->Header.Negative == 0) @@ -761,25 +767,32 @@ static void OneLine4(struct ico_progressive_state *context) while (X < context->Header.width) { guchar Pix; + guint8 idx; Pix = context->LineBuf[X/2]; + idx = Pix >> 4; + if (idx >= palette_size) + idx = 0; Pixels[X * 4 + 0] = - context->HeaderBuf[4 * (Pix>>4) + INFOHEADER_SIZE + 2 + context->DIBoffset]; + context->HeaderBuf[4 * idx + INFOHEADER_SIZE + 2 + context->DIBoffset]; Pixels[X * 4 + 1] = - context->HeaderBuf[4 * (Pix>>4) + INFOHEADER_SIZE + 1 +context->DIBoffset]; + context->HeaderBuf[4 * idx + INFOHEADER_SIZE + 1 +context->DIBoffset]; Pixels[X * 4 + 2] = - context->HeaderBuf[4 * (Pix>>4) + INFOHEADER_SIZE + context->DIBoffset]; + context->HeaderBuf[4 * idx + INFOHEADER_SIZE + context->DIBoffset]; Pixels[X * 4 + 3] = 0xff; X++; - if (XHeader.width) { + if (XHeader.width) { /* Handle the other 4 bit pixel only when there is one */ + idx = Pix & 15; + if (idx >= palette_size) + idx = 0; Pixels[X * 4 + 0] = - context->HeaderBuf[4 * (Pix&15) + INFOHEADER_SIZE + 2 + context->DIBoffset]; + context->HeaderBuf[4 * idx + INFOHEADER_SIZE + 2 + context->DIBoffset]; Pixels[X * 4 + 1] = - context->HeaderBuf[4 * (Pix&15) + INFOHEADER_SIZE + 1 + context->DIBoffset]; + context->HeaderBuf[4 * idx + INFOHEADER_SIZE + 1 + context->DIBoffset]; Pixels[X * 4 + 2] = - context->HeaderBuf[4 * (Pix&15) + INFOHEADER_SIZE + context->DIBoffset]; + context->HeaderBuf[4 * idx + INFOHEADER_SIZE + context->DIBoffset]; Pixels[X * 4 + 3] = 0xff; X++; } -- GitLab