Re: libgd 2.0.33 infinite loop in GIF decoding ?
rocheml@xxxxxxxxxxx wrote:
1. Bug
------
A bug seems to affect the current (2.0.33) GD library version, located
in the LZW decoding while loading GIF images. The problem is an infinite
loop while decoding specifically crafted images ; for example when
calling gdImageCreateFromGifPtr() with badly formed GIF data. The loop
is causing 100% CPU consumption, and can be a problem when involving
online server scripts.
A second bug exists in gd_gif_in.c:152, which can make corrupted
(truncated) GIF files to generate an infinite loop in libgd.
2. Example #2
-------------
/* id: gdbad2.c, Xavier Roche, May. 2006 */
/* gcc gdbad2.c -o bad -lgd && ./bad */
#include <stdio.h>
#include <stdlib.h>
#include "gd.h"
static const unsigned char gifdata[157];
int main(void) {
gdImagePtr im;
if ( ( im = gdImageCreateFromGifPtr(157, (char*) &gifdata[0]) ) !=
NULL) {
fprintf(stderr, "success!\n");
gdImageDestroy(im);
} else {
fprintf(stderr, "failed!\n");
}
return 0;
}
/* GIF data */
static const unsigned char gifdata[157] = {71,73,70,56,57,97,7,0,15,0,
227,0,0,221,221,221,205,205,205,188,188,188,171,171,171,155,155,155,138,
138,138,121,121,121,105,105,105,88,88,88,72,72,72,55,55,55,38,38,38,22,
22,22,5,5,5,0,0,0,255,255,255,33,254,21,67,114,101,97,116,101,100,32,
119,105,116,104,32,84,104,101,32,71,73,77,80,0,33,249,4,1,13,10,0,15,0,
44,0,0,0,0,7,0,15,0,0,4,48,16,128,71,105,184,161,138,189,233,248,224,67,
140,228,83,156,104,97,172,172,113,188,240,129,204,52,146,220,120,162,
236,252,179,252,192,7,99,56,164,52,142,141,138,195,81,161,68,0,0,59};
3. Quick fix #2
---------------
*** gd-2.0.33.orig/gd_gif_in.c Mon Nov 1 19:28:56 2004
--- gd-2.0.33/gd_gif_in.c Fri Jun 9 15:09:45 2006
***************
*** 99,104 ****
--- 99,105 ----
BGD_DECLARE(gdImagePtr) gdImageCreateFromGifCtx(gdIOCtxPtr fd)
{
+ int maxcount = 1024;
int BitPixel;
#if 0
int ColorResolution;
***************
*** 164,169 ****
--- 165,172 ----
}
if (c != ',') { /* Not a valid start character */
+ if (--maxcount < 0)
+ goto terminated; /* Looping */
continue;
}
***************
*** 241,246 ****
--- 244,250 ----
static int
DoExtension(gdIOCtx *fd, int label, int *Transparent, int
*ZeroDataBlockP)
{
+ int maxcount = 1024;
static unsigned char buf[256];
switch (label) {
***************
*** 254,266 ****
if ((buf[0] & 0x1) != 0)
*Transparent = buf[3];
! while (GetDataBlock(fd, (unsigned char*) buf,
ZeroDataBlockP) != 0)
;
return FALSE;
default:
break;
}
! while (GetDataBlock(fd, (unsigned char*) buf, ZeroDataBlockP) != 0)
;
return FALSE;
--- 258,272 ----
if ((buf[0] & 0x1) != 0)
*Transparent = buf[3];
! while (GetDataBlock(fd, (unsigned char*) buf,
! ZeroDataBlockP) != 0 && --maxcount
>= 0)
;
return FALSE;
default:
break;
}
! while (GetDataBlock(fd, (unsigned char*) buf, ZeroDataBlockP) != 0
! && --maxcount >= 0)
;
return FALSE;
***************
*** 417,432 ****
GetCode(fd, code_size, FALSE,
ZeroDataBlockP);
return firstcode;
} else if (code == end_code) {
int count;
unsigned char buf[260];
if (*ZeroDataBlockP)
return -2;
! while ((count = GetDataBlock(fd, buf,
ZeroDataBlockP)) > 0)
;
! if (count != 0)
return -2;
}
--- 423,439 ----
GetCode(fd, code_size, FALSE,
ZeroDataBlockP);
return firstcode;
} else if (code == end_code) {
+ int maxcount = 1024;
int count;
unsigned char buf[260];
if (*ZeroDataBlockP)
return -2;
! while ((count = GetDataBlock(fd, buf,
ZeroDataBlockP)) > 0 && --maxcount >= 0)
;
! if (count != 0 || maxcount < 0)
return -2;
}