libGD

GD is an open source code library for the dynamic creation of images by programmers. GD is written in C, and “wrappers” are available for Perl, PHP and other languages. GD creates PNG, JPEG and GIF images, among other formats. GD is commonly used to generate charts, graphics, thumbnails, and most anything else, on the fly. While not restricted to use on the web, the most common applications of GD involve web site development.

See the GD website for more informations.

Tasklist

FS#86 — Possible infinite loop in libgd/gd_png.c (inside png_set_read_fn() callback) with truncated input

Attached to Project — libGD
Opened by Xavier Roche (xroche) - Wednesday, 16 May 2007, 14:12 GMT+1
Last edited by Pierre Joye (Pierre) - Thursday, 17 May 2007, 16:50 GMT+1
Task Type Bug Report
Category Image Import/Export
Status Closed
Assigned To Pierre Joye (Pierre)
Operating System All
Severity High
Priority Normal
Reported Version 2.0.34
Due in Version 2.0.35
Due Date Undecided
Percent Complete 100%
Votes 0
Private No

Details

Hi folks,

The following test case using libgd 2.0.34 apparently leads to an infinite loop in the libpng decoder.

The infinite loop seems to occur between the libpng code (png_read_data()) and the libgd callback (gdPngReadData()) which may not properly detect truncated input. The libpng’s png_read_info() function hence never returns, and the library consumme 100% CPU.

/* id: gdbad3.c, Xavier Roche, May. 2007 */
/* gcc gdbad3.c -o bad -lgd && ./bad */

#include <stdio.h>
#include <stdlib.h>
#include "gd.h"

static const unsigned char pngdata[93];
int main(void) {
  gdImagePtr im;
  if ( ( im = gdImageCreateFromPngPtr(93, (char*) &pngdata[0]) ) != NULL) {
    fprintf(stderr, "success!\n");
    gdImageDestroy(im);
  } else {
    fprintf(stderr, "failed!\n");
  }
  return 0;
}

/* PNG data */
static const unsigned char pngdata[93] = {137,80,78,71,13,10,26,10,0,0,
0,13,73,72,68,82,0,0,0,120,0,0,0,131,8,6,0,0,0,70,49,223,8,0,0,0,6,98,
75,71,68,0,255,0,255,0,255,160,189,167,147,0,0,0,9,112,72,89,115,0,0,92,
70,0,0,92,70,1,20,148,67,65,0,0,0,9,118,112,65,103,0,0,0,120,0,0,0,131,
0,226,13,249,45};

Typical stack:

(gdb) where
#0  gdPngReadData (png_ptr=0x501090, data=0x501570 "", length=5247120) at gd_png.c:83
#1  0x00002af9ef5ab192 in png_read_data (png_ptr=0x501090, data=0x501570 "", length=9) at pngrio.c:33
#2  0x00002af9ef5a1935 in png_crc_read (png_ptr=0x501090, buf=0x501570 "", length=9) at pngrutil.c:96
#3  0x00002af9ef5a1a17 in png_crc_finish (png_ptr=0x501090, skip=5248368) at pngrutil.c:116
#4  0x00002af9ef5a425a in png_handle_unknown (png_ptr=0x501090, info_ptr=0x505ae0, length=9)
    at pngrutil.c:2221
#5  0x00002af9ef5a9e0d in png_read_info (png_ptr=0x501090, info_ptr=0x505ae0) at pngread.c:530
#6  0x00002af9eeb2baf9 in gdImageCreateFromPngCtx (infile=0x501010) at gd_png.c:189
#7  0x00002af9eeb2b9b0 in gdImageCreateFromPngPtr (size=5247120, data=0x501570) at gd_png.c:111
#8  0x00000000004006df in main ()

(if you ‘up’ to png_read_info() and try ‘finish’, you’ll see that this function never returns due to endless calls to gdPngReadData())

This task depends upon

Closed by  Pierre Joye (Pierre)
Thursday, 17 May 2007, 16:50 GMT+1
Reason for closing:  Fixed
Additional comments about closing:  Commit in GD_2_0 and HEAD (2.1)
Comment by Pierre Joye (Pierre) - Wednesday, 16 May 2007, 14:58 GMT+1
  • Field changed: Status (Unconfirmed → Waiting on Customer)

I cannot test it right now but have you tried to read it directly with the libpng (sample codes for example)?

At this stage, gd has no control over the reading process, we checked the signature and then pass the data to the libpng. The backtrace looks like you are refering to CVE-2007-2445, which is a libpng issue and fixed in libpng 1.2.17. Is it correct?

Comment by Xavier Roche (xroche) - Wednesday, 16 May 2007, 15:30 GMT+1

The issue was reproduced with libpng 1.2.18.

The libpng "pngtest" example detect the truncated file, and fails (no infinite loop):

$ make pngtest
..
$ ./pngtest gdbad3.png gdbad3.png.2
Testing libpng version 1.2.18
   with zlib   version 1.2.3

 libpng version 1.2.18 - May 15, 2007
   Copyright (c) 1998-2007 Glenn Randers-Pehrson
   Copyright (c) 1996-1997 Andreas Dilger
   Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
 library (10218): libpng version 1.2.18 - May 15, 2007 (header)
 pngtest (10218): libpng version 1.2.18 - May 15, 2007 (header)
 png_sizeof(png_struct)=1240, png_sizeof(png_info)=464
libpng error: Read Error
Testing gdbad3.png:gdbad3.png -> gdbad3.png.2: libpng read error
Testing gdbad3.png: FAIL
libpng error: Read Error
Testing gdbad3.png:gdbad3.png -> gdbad3.png.2: libpng read error
Testing gdbad3.png: FAIL
libpng error: Read Error
Testing gdbad3.png:gdbad3.png -> gdbad3.png.2: libpng read error
 FAIL
libpng FAILS test

Something wicked must happend inside gdPngReadData()

Comment by Pierre Joye (Pierre) - Wednesday, 16 May 2007, 21:33 GMT+1

Problem found, readdata should have been updated to be synced with libpng recommended usage.

Please try the attached patch, it should fix the problem. If everything works well, it will be part of 2.0.35RC4.

Thanks again for the detailed report!

Comment by Xavier Roche (xroche) - Wednesday, 16 May 2007, 22:05 GMT+1

Looks fine after the patch! Thanks! :p

./bad
gd-png:  fatal libpng error: Read Error: truncated data
gd-png error: setjmp returns error condition 1
failed!
Comment by Pierre Joye (Pierre) - Thursday, 17 May 2007, 00:59 GMT+1

For the record, I just applied the fix to php's libgd. It will be available in the php releases (4.4.8, 5.2.3 and later).

Comment by Pierre Joye (Pierre) - Tuesday, 22 May 2007, 16:49 GMT+1

It is now referenced as CVE-2007-2756.

Loading...