summaryrefslogtreecommitdiff
path: root/graphics/SDL_image/patches/patch-IMG__pcx.c
diff options
context:
space:
mode:
Diffstat (limited to 'graphics/SDL_image/patches/patch-IMG__pcx.c')
-rw-r--r--graphics/SDL_image/patches/patch-IMG__pcx.c154
1 files changed, 154 insertions, 0 deletions
diff --git a/graphics/SDL_image/patches/patch-IMG__pcx.c b/graphics/SDL_image/patches/patch-IMG__pcx.c
new file mode 100644
index 00000000000..0c0498f2c98
--- /dev/null
+++ b/graphics/SDL_image/patches/patch-IMG__pcx.c
@@ -0,0 +1,154 @@
+$NetBSD: patch-IMG__pcx.c,v 1.1 2020/05/14 16:08:07 nia Exp $
+
+Various sanity fixes from upstream preventing potential
+security problems.
+
+--- IMG_pcx.c.orig 2012-01-21 01:51:33.000000000 +0000
++++ IMG_pcx.c
+@@ -100,6 +100,8 @@ SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *s
+ Uint8 *row, *buf = NULL;
+ char *error = NULL;
+ int bits, src_bits;
++ int count = 0;
++ Uint8 ch;
+
+ if ( !src ) {
+ /* The error message has been set in SDL_RWFromFile */
+@@ -127,37 +129,37 @@ SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *s
+ bits = 8;
+ } else if(pcxh.BitsPerPixel == 8 && pcxh.NPlanes == 3) {
+ bits = 24;
+- if ( SDL_BYTEORDER == SDL_LIL_ENDIAN ) {
+- Rmask = 0x000000FF;
+- Gmask = 0x0000FF00;
+- Bmask = 0x00FF0000;
+- } else {
+- Rmask = 0xFF0000;
+- Gmask = 0x00FF00;
+- Bmask = 0x0000FF;
+- }
++#if SDL_BYTEORDER == SDL_LIL_ENDIAN
++ Rmask = 0x000000FF;
++ Gmask = 0x0000FF00;
++ Bmask = 0x00FF0000;
++#else
++ Rmask = 0xFF0000;
++ Gmask = 0x00FF00;
++ Bmask = 0x0000FF;
++#endif
+ } else {
+ error = "unsupported PCX format";
+ goto done;
+ }
+ surface = SDL_AllocSurface(SDL_SWSURFACE, width, height,
+ bits, Rmask, Gmask, Bmask, Amask);
+- if ( surface == NULL )
++ if ( surface == NULL ) {
+ goto done;
++ }
+
+ bpl = pcxh.NPlanes * pcxh.BytesPerLine;
+- if (bpl > surface->pitch) {
+- error = "bytes per line is too large (corrupt?)";
++ buf = (Uint8 *)calloc(bpl, 1);
++ if (!buf) {
++ error = "Out of memory";
++ goto done;
+ }
+- buf = malloc(bpl);
+- row = surface->pixels;
++ row = (Uint8 *)surface->pixels;
+ for ( y=0; y<surface->h; ++y ) {
+ /* decode a scan line to a temporary buffer first */
+- int i, count = 0;
+- Uint8 ch;
+- Uint8 *dst = (src_bits == 8) ? row : buf;
++ int i;
+ if ( pcxh.Encoding == 0 ) {
+- if(!SDL_RWread(src, dst, bpl, 1)) {
++ if(!SDL_RWread(src, buf, bpl, 1)) {
+ error = "file truncated";
+ goto done;
+ }
+@@ -168,46 +170,54 @@ SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *s
+ error = "file truncated";
+ goto done;
+ }
+- if( (ch & 0xc0) == 0xc0) {
+- count = ch & 0x3f;
++ if (ch < 0xc0) {
++ count = 1;
++ } else {
++ count = ch - 0xc0;
+ if(!SDL_RWread(src, &ch, 1, 1)) {
+ error = "file truncated";
+ goto done;
+ }
+- } else
+- count = 1;
++ }
+ }
+- dst[i] = ch;
++ buf[i] = ch;
+ count--;
+ }
+ }
+
+ if(src_bits <= 4) {
+ /* expand planes to 1 byte/pixel */
+- Uint8 *src = buf;
++ Uint8 *innerSrc = buf;
+ int plane;
+ for(plane = 0; plane < pcxh.NPlanes; plane++) {
+- int i, j, x = 0;
+- for(i = 0; i < pcxh.BytesPerLine; i++) {
+- Uint8 byte = *src++;
+- for(j = 7; j >= 0; j--) {
+- unsigned bit = (byte >> j) & 1;
++ int j, k, x = 0;
++ for(j = 0; j < pcxh.BytesPerLine; j++) {
++ Uint8 byte = *innerSrc++;
++ for(k = 7; k >= 0; k--) {
++ unsigned bit = (byte >> k) & 1;
+ /* skip padding bits */
+- if (i * 8 + j >= width)
++ if (j * 8 + k >= width)
+ continue;
+ row[x++] |= bit << plane;
+ }
+ }
+ }
++ } else if(src_bits == 8) {
++ /* Copy the row directly */
++ memcpy(row, buf, SDL_min(width, bpl));
+ } else if(src_bits == 24) {
+ /* de-interlace planes */
+- Uint8 *src = buf;
++ Uint8 *innerSrc = buf;
+ int plane;
+ for(plane = 0; plane < pcxh.NPlanes; plane++) {
+ int x;
+- dst = row + plane;
++ Uint8 *dst = row + plane;
+ for(x = 0; x < width; x++) {
+- *dst = *src++;
++ if (dst >= row+surface->pitch) {
++ error = "decoding out of bounds (corrupt?)";
++ goto done;
++ }
++ *dst = *innerSrc++;
+ dst += pcxh.NPlanes;
+ }
+ }
+@@ -227,8 +237,9 @@ SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *s
+ /* look for a 256-colour palette */
+ do {
+ if ( !SDL_RWread(src, &ch, 1, 1)) {
+- error = "file truncated";
+- goto done;
++ /* Couldn't find the palette, try the end of the file */
++ SDL_RWseek(src, -768, RW_SEEK_END);
++ break;
+ }
+ } while ( ch != 12 );
+