--- zgv-5.8/ChangeLog Mon Mar 29 05:34:03 2004 +++ zgv-5.8/ChangeLog Sun Oct 31 15:23:27 2004 @@ -1,3 +1,27 @@ +2004-10-31 Russell Marks + + * Added width/height limits to all picture readers, 32767x32767 is + now the maximum image size supported (consistent with xzgv). This + is a crude (albeit effective) fix for heap overflow bugs - there + may yet be more subtle problems, but I can't really fix them until + I know they're there. :-) Thanks to Luke Macken for letting me + know about the heap overflow problems. I suppose I should also + thank "infamous41md" for publishing the original exploit (for the + XPM colours bug), even if he didn't bother emailing me or + anything. + + * src/readxpm.c (read_xpm_file): fix for exploitable malloc() arg + overflow. There are several more of these in zgv, but this is the + easiest to fix. + +2004-07-08 Russell Marks + + * src/readgif.c (read_gif_file): added more multiple-image (e.g. + animated) GIF brokenness checks than before. Previously it was + possible to get a segfault with the `right' file, despite there + already being various range checks. Thanks to Mikulas Patocka for + spotting this. + 2004-03-29 Russell Marks * Version 5.8. --- zgv-5.8/src/readbmp.c Thu Oct 4 16:48:36 2001 +++ zgv-5.8/src/readbmp.c Sun Oct 31 14:32:44 2004 @@ -177,7 +177,8 @@ bytepp=1; if ((pp->bpp == 24) && (*output_type == 3)) bytepp = 3; - if ((work_bmap = *bmap = calloc (w * (h + 2) * bytepp,1)) == NULL) + if (WH_BAD(w,h) || + (work_bmap = *bmap = calloc (w * (h + 2) * bytepp,1)) == NULL) CLOSE_AND_RET(_PICERR_NOMEM); bytes_in_image=w*h*bytepp; --- zgv-5.8/src/readgif.c Sat Mar 15 02:39:42 2003 +++ zgv-5.8/src/readgif.c Sun Oct 31 14:31:48 2004 @@ -491,7 +491,7 @@ readcolmap(in,im->cmap,lnumcols); } - if((im->image=(byte *)malloc(width*height))==NULL) + if(WH_BAD(width,height) || (im->image=(byte *)malloc(width*height))==NULL) { fclose(in); return(_PICERR_NOMEM); @@ -599,7 +599,8 @@ /* allocate main image and palette */ -if((*theimageptr=(byte *)malloc(ginfo->width*ginfo->height))==NULL) +if(WH_BAD(ginfo->width,ginfo->height) || + (*theimageptr=(byte *)malloc(ginfo->width*ginfo->height))==NULL) { images_cleanup(); return(_PICERR_NOMEM); @@ -668,7 +669,11 @@ for(i=0;iwidth>swidth) images[i]->width=swidth; + if(images[i]->height>sheight) images[i]->height=sheight; /* for images after the first, we need to set the initial contents * (as far as GIF is concerned, the `screen' contents) as directed @@ -708,20 +713,28 @@ */ } } - - ptr1=ptr+images[i]->left+images[i]->top*swidth; - ptr2=images[i]->image; - - for(y=0;yheight;y++) + + /* an image with left or top offscreen is broken, but relying + * unknowingly on the image not appearing at all. So skip it. + */ + if(images[i]->lefttopwidth;x++) - if(!(images[i]->gcb_control&1) || /* if no transparent col defined */ - images[i]->transparent_col!=*ptr2) - *ptr1++=*ptr2++; - else - ptr1++,ptr2++; + ptr1=ptr+images[i]->left+images[i]->top*swidth; - ptr1+=swidth-images[i]->width; + for(y=0;yheight && images[i]->top+yimage+y*images[i]->width; + + for(x=0;xwidth && images[i]->left+xgcb_control&1) || /* if no transparent col defined */ + images[i]->transparent_col!=*ptr2) + *ptr1++=*ptr2++; + else + ptr1++,ptr2++; + + ptr1=oldptr1+swidth; + } } ptr+=swidth*sheight; --- zgv-5.8/src/readjpeg.c Wed Sep 27 17:28:30 2000 +++ zgv-5.8/src/readjpeg.c Sun Oct 31 14:54:26 2004 @@ -190,10 +190,10 @@ height=cinfo.output_height; } -theimage=(byte *)malloc(pixelsize*width*height); -if(theimage==NULL) +if(WH_BAD(width,height) || + (theimage=(byte *)malloc(pixelsize*width*height))==NULL) { - jpegerr("Out of memory"); + jpegerr("Out of memory"); /* XXX misleading if width/height are bad */ longjmp(jerr.setjmp_buffer,1); } --- zgv-5.8/src/readmrf.c Wed Oct 21 07:28:23 1998 +++ zgv-5.8/src/readmrf.c Sun Oct 31 14:56:33 2004 @@ -103,7 +103,8 @@ w64=(w+63)/64; h64=(h+63)/64; -if((*bmap=malloc(w*h))==NULL || +if(WH_BAD(w64*64,h64*64) || WH_BAD(w,h) || + (*bmap=malloc(w*h))==NULL || (image=calloc(w64*h64*64*64,1))==NULL) CLOSE_AND_RET(_PICERR_NOMEM); --- zgv-5.8/src/readpcd.c Thu Sep 30 01:56:59 1999 +++ zgv-5.8/src/readpcd.c Sun Oct 31 14:57:37 2004 @@ -39,7 +39,7 @@ if((*output_type)!=1)*output_type=3; -if((*bmap=malloc(w*(h+3-*output_type)*(*output_type)))==NULL) +if(WH_BAD(w,h) || (*bmap=malloc(w*(h+3-*output_type)*(*output_type)))==NULL) return(_PICERR_NOMEM); if((*pal=malloc(768))==NULL) --- zgv-5.8/src/readpcx.c Wed Mar 31 00:11:36 1999 +++ zgv-5.8/src/readpcx.c Sun Oct 31 14:59:30 2004 @@ -127,7 +127,7 @@ bytemax=(1<<30); /* we use a 'y(1<<24) || (colchars=malloc(ncols*sizeof(struct colchars_tag)))==NULL) CLOSE_AND_RET(_PICERR_NOMEM); @@ -369,7 +369,7 @@ */ /* extra lines are in case we're dithering. */ -if((*bmap=malloc(w*(h+2)*bytepp))==NULL) +if(WH_BAD(w,h) || (*bmap=malloc(w*(h+2)*bytepp))==NULL) CLOSE_AND_RET(_PICERR_NOMEM); ptr=*bmap; --- zgv-5.8/src/zgv.h Sat Feb 21 16:31:29 2004 +++ zgv-5.8/src/zgv.h Sun Oct 31 14:58:34 2004 @@ -66,3 +66,12 @@ /* make 15/16-bit colours, used in a few different places */ #define GET15BITCOLOUR(r,g,b) ((((r)&0xf8)<<7)|(((g)&0xf8)<<2)|((b)>>3)) #define GET16BITCOLOUR(r,g,b) ((((r)&0xf8)<<8)|(((g)&0xfc)<<3)|((b)>>3)) + +/* range check on width and height as a crude way of avoiding overflows + * when calling malloc/calloc. The maximum we can allow is around 37000, + * but 32767 at least makes it consistent with xzgv. :-) + * Adds an extra 2 to height for max-height check, as we usually allocate + * 2 more lines to allow for dithering. + */ +#define WH_MAX 32767 +#define WH_BAD(w,h) ((w)<=0 || (w)>WH_MAX || (h)<=0 || ((h)+2)>WH_MAX)