pcx: backport security and bug fixes from the main 2.0 branch: SDL-1.2
authorOzkan Sezer
Wed, 10 Jul 2019 23:35:11 +0300
branchSDL-1.2
changeset 676441241ea7d07
parent 675 e6732a14e531
child 677 b875cfe43ddf
pcx: backport security and bug fixes from the main 2.0 branch:
TALOS-2019-0841: heap buffer overlow exploit
TALOS-2019-0821: reading invalid data from the file when bpl is -1
mainstream commits:
https://hg.libsdl.org/SDL_image/rev/7453e79c8cdb
https://hg.libsdl.org/SDL_image/rev/b920be2b3fc6
https://hg.libsdl.org/SDL_image/rev/e7e9786a1a34
https://hg.libsdl.org/SDL_image/rev/94e5942b92af
IMG_pcx.c
     1.1 --- a/IMG_pcx.c	Mon Jun 10 16:31:02 2019 -0700
     1.2 +++ b/IMG_pcx.c	Wed Jul 10 23:35:11 2019 +0300
     1.3 @@ -100,6 +100,8 @@
     1.4  	Uint8 *row, *buf = NULL;
     1.5  	char *error = NULL;
     1.6  	int bits, src_bits;
     1.7 +	int count = 0;
     1.8 +	Uint8 ch;
     1.9  
    1.10  	if ( !src ) {
    1.11  		/* The error message has been set in SDL_RWFromFile */
    1.12 @@ -117,6 +119,20 @@
    1.13  	pcxh.Ymax = SDL_SwapLE16(pcxh.Ymax);
    1.14  	pcxh.BytesPerLine = SDL_SwapLE16(pcxh.BytesPerLine);
    1.15  
    1.16 +#if 0
    1.17 +	printf("Manufacturer = %d\n", pcxh.Manufacturer);
    1.18 +	printf("Version = %d\n", pcxh.Version);
    1.19 +	printf("Encoding = %d\n", pcxh.Encoding);
    1.20 +	printf("BitsPerPixel = %d\n", pcxh.BitsPerPixel);
    1.21 +	printf("Xmin = %d, Ymin = %d, Xmax = %d, Ymax = %d\n", pcxh.Xmin, pcxh.Ymin, pcxh.Xmax, pcxh.Ymax);
    1.22 +	printf("HDpi = %d, VDpi = %d\n", pcxh.HDpi, pcxh.VDpi);
    1.23 +	printf("NPlanes = %d\n", pcxh.NPlanes);
    1.24 +	printf("BytesPerLine = %d\n", pcxh.BytesPerLine);
    1.25 +	printf("PaletteInfo = %d\n", pcxh.PaletteInfo);
    1.26 +	printf("HscreenSize = %d\n", pcxh.HscreenSize);
    1.27 +	printf("VscreenSize = %d\n", pcxh.VscreenSize);
    1.28 +#endif
    1.29 +
    1.30  	/* Create the surface of the appropriate type */
    1.31  	width = (pcxh.Xmax - pcxh.Xmin) + 1;
    1.32  	height = (pcxh.Ymax - pcxh.Ymin) + 1;
    1.33 @@ -142,22 +158,22 @@
    1.34  	}
    1.35  	surface = SDL_AllocSurface(SDL_SWSURFACE, width, height,
    1.36  				   bits, Rmask, Gmask, Bmask, Amask);
    1.37 -	if ( surface == NULL )
    1.38 +	if ( surface == NULL ) {
    1.39  		goto done;
    1.40 +	}
    1.41  
    1.42  	bpl = pcxh.NPlanes * pcxh.BytesPerLine;
    1.43 -	if (bpl > surface->pitch) {
    1.44 -		error = "bytes per line is too large (corrupt?)";
    1.45 +	buf = (Uint8 *)calloc(bpl, 1);
    1.46 +	if (!buf) {
    1.47 +		error = "Out of memory";
    1.48 +		goto done;
    1.49  	}
    1.50 -	buf = (Uint8 *)calloc(SDL_max(bpl, surface->pitch), 1);
    1.51  	row = (Uint8 *)surface->pixels;
    1.52  	for ( y=0; y<surface->h; ++y ) {
    1.53  		/* decode a scan line to a temporary buffer first */
    1.54 -		int i, count = 0;
    1.55 -		Uint8 ch;
    1.56 -		Uint8 *dst = (src_bits == 8) ? row : buf;
    1.57 +		int i;
    1.58  		if ( pcxh.Encoding == 0 ) {
    1.59 -			if(!SDL_RWread(src, dst, bpl, 1)) {
    1.60 +			if(!SDL_RWread(src, buf, bpl, 1)) {
    1.61  				error = "file truncated";
    1.62  				goto done;
    1.63  			}
    1.64 @@ -168,16 +184,17 @@
    1.65  						error = "file truncated";
    1.66  						goto done;
    1.67  					}
    1.68 -					if( (ch & 0xc0) == 0xc0) {
    1.69 -						count = ch & 0x3f;
    1.70 +					if (ch < 0xc0) {
    1.71 +						count = 1;
    1.72 +					} else {
    1.73 +						count = ch - 0xc0;
    1.74  						if(!SDL_RWread(src, &ch, 1, 1)) {
    1.75  							error = "file truncated";
    1.76  							goto done;
    1.77  						}
    1.78 -					} else
    1.79 -						count = 1;
    1.80 +					}
    1.81  				}
    1.82 -				dst[i] = ch;
    1.83 +				buf[i] = ch;
    1.84  				count--;
    1.85  			}
    1.86  		}
    1.87 @@ -199,14 +216,21 @@
    1.88  					}
    1.89  				}
    1.90  			}
    1.91 +		} else if(src_bits == 8) {
    1.92 +			/* Copy the row directly */
    1.93 +			memcpy(row, buf, SDL_min(width, bpl));
    1.94   		} else if(src_bits == 24) {
    1.95  			/* de-interlace planes */
    1.96  			Uint8 *innerSrc = buf;
    1.97  			int plane;
    1.98  			for(plane = 0; plane < pcxh.NPlanes; plane++) {
    1.99  				int x;
   1.100 -				dst = row + plane;
   1.101 +				Uint8 *dst = row + plane;
   1.102  				for(x = 0; x < width; x++) {
   1.103 +					if (dst >= row+surface->pitch) {
   1.104 +						error = "decoding out of bounds (corrupt?)";
   1.105 +						goto done;
   1.106 +					}
   1.107  					*dst = *innerSrc++;
   1.108  					dst += pcxh.NPlanes;
   1.109  				}
   1.110 @@ -227,8 +251,9 @@
   1.111  			/* look for a 256-colour palette */
   1.112  			do {
   1.113  				if ( !SDL_RWread(src, &ch, 1, 1)) {
   1.114 -					error = "file truncated";
   1.115 -					goto done;
   1.116 +					/* Couldn't find the palette, try the end of the file */
   1.117 +					SDL_RWseek(src, -768, RW_SEEK_END);
   1.118 +					break;
   1.119  				}
   1.120  			} while ( ch != 12 );
   1.121