X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;ds=sidebyside;f=image_png.c;h=6cf182a1e94a958f2491754940c60d1bed702ecc;hb=2942e1d5fa49af36df6611b9d43f819d2de95ee5;hp=d9d7a5004f844dfe13aacdfc444493507b56e6d4;hpb=a19dce25671ecfa28e4eb3861f8636750bf3ba68;p=xonotic%2Fdarkplaces.git diff --git a/image_png.c b/image_png.c index d9d7a500..6cf182a1 100644 --- a/image_png.c +++ b/image_png.c @@ -50,7 +50,7 @@ static unsigned int (*qpng_get_valid) (void*, void*, unsigned int); static unsigned int (*qpng_get_rowbytes) (void*, void*); static unsigned char (*qpng_get_channels) (void*, void*); static unsigned char (*qpng_get_bit_depth) (void*, void*); -static unsigned int (*qpng_get_IHDR) (void*, void*, unsigned int*, unsigned int*, int *, int *, int *, int *, int *); +static unsigned int (*qpng_get_IHDR) (void*, void*, unsigned long*, unsigned long*, int *, int *, int *, int *, int *); static char* (*qpng_get_libpng_ver) (void*); static dllfunction_t pngfuncs[] = @@ -189,8 +189,8 @@ static struct int BitDepth; int BytesPerPixel; int ColorType; - unsigned int Height; - unsigned int Width; + unsigned long Height; // retarded libpng 1.2 pngconf.h uses long (64bit/32bit depending on arch) + unsigned long Width; // retarded libpng 1.2 pngconf.h uses long (64bit/32bit depending on arch) int Interlace; int Compression; int Filter; @@ -233,7 +233,7 @@ unsigned char *PNG_LoadImage (const unsigned char *raw, int filesize, int matchw { unsigned int y; void *png, *pnginfo; - unsigned char *imagedata; + unsigned char *imagedata = NULL; unsigned char ioBuffer[8192]; // FIXME: register an error handler so that abort() won't be called on error @@ -248,6 +248,10 @@ unsigned char *PNG_LoadImage (const unsigned char *raw, int filesize, int matchw if(!png) return NULL; + // this must be memset before the setjmp error handler, because it relies + // on the fields in this struct for cleanup + memset(&my_png, 0, sizeof(my_png)); + // NOTE: this relies on jmp_buf being the first thing in the png structure // created by libpng! (this is correct for libpng 1.2.x) #ifdef __cplusplus @@ -260,6 +264,12 @@ unsigned char *PNG_LoadImage (const unsigned char *raw, int filesize, int matchw if (setjmp(png)) #endif { + if (my_png.Data) + Mem_Free(my_png.Data); + my_png.Data = NULL; + if (my_png.FRowPtrs) + Mem_Free(my_png.FRowPtrs); + my_png.FRowPtrs = NULL; qpng_destroy_read_struct(&png, &pnginfo, 0); return NULL; } @@ -273,7 +283,6 @@ unsigned char *PNG_LoadImage (const unsigned char *raw, int filesize, int matchw } qpng_set_sig_bytes(png, 0); - memset(&my_png, 0, sizeof(my_png)); my_png.tmpBuf = raw; my_png.tmpBuflength = filesize; my_png.tmpi = 0; @@ -288,7 +297,21 @@ unsigned char *PNG_LoadImage (const unsigned char *raw, int filesize, int matchw qpng_set_read_fn(png, ioBuffer, (void *)PNG_fReadData); qpng_read_info(png, pnginfo); qpng_get_IHDR(png, pnginfo, &my_png.Width, &my_png.Height,&my_png.BitDepth, &my_png.ColorType, &my_png.Interlace, &my_png.Compression, &my_png.Filter); - if ((matchwidth && my_png.Width != (unsigned int)matchwidth) || (matchheight && my_png.Height != (unsigned int)matchheight)) + + // this check guards against pngconf.h with unsigned int *width/height parameters on big endian systems by detecting the strange values and shifting them down 32bits + // (if it's little endian the unwritten bytes are the most significant + // ones and we don't worry about that) + // + // this is only necessary because of retarded 64bit png_uint_32 types in libpng 1.2, which can (conceivably) vary by platform +#if LONG_MAX > 4000000000 + if (my_png.Width > LONG_MAX || my_png.Height > LONG_MAX) + { + my_png.Width >>= 32; + my_png.Height >>= 32; + } +#endif + + if ((matchwidth && my_png.Width != (unsigned long)matchwidth) || (matchheight && my_png.Height != (unsigned long)matchheight)) { qpng_destroy_read_struct(&png, &pnginfo, 0); return NULL; @@ -319,9 +342,10 @@ unsigned char *PNG_LoadImage (const unsigned char *raw, int filesize, int matchw my_png.FRowPtrs = (unsigned char **)Mem_Alloc(tempmempool, my_png.Height * sizeof(*my_png.FRowPtrs)); if (my_png.FRowPtrs) { - my_png.Data = (unsigned char *)Mem_Alloc(tempmempool, my_png.Height * my_png.FRowBytes); - if(my_png.Data) + imagedata = (unsigned char *)Mem_Alloc(tempmempool, my_png.Height * my_png.FRowBytes); + if(imagedata) { + my_png.Data = imagedata; for(y = 0;y < my_png.Height;y++) my_png.FRowPtrs[y] = my_png.Data + y * my_png.FRowBytes; qpng_read_image(png, my_png.FRowPtrs); @@ -329,6 +353,7 @@ unsigned char *PNG_LoadImage (const unsigned char *raw, int filesize, int matchw else Con_DPrintf("PNG_LoadImage : not enough memory\n"); Mem_Free(my_png.FRowPtrs); + my_png.FRowPtrs = NULL; } else Con_DPrintf("PNG_LoadImage : not enough memory\n"); @@ -336,9 +361,8 @@ unsigned char *PNG_LoadImage (const unsigned char *raw, int filesize, int matchw qpng_read_end(png, pnginfo); qpng_destroy_read_struct(&png, &pnginfo, 0); - image_width = my_png.Width; - image_height = my_png.Height; - imagedata = my_png.Data; + image_width = (int)my_png.Width; + image_height = (int)my_png.Height; if (my_png.BitDepth != 8) {