1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
|
From: Sam Lantinga <slouken@libsdl.org>
Date: Mon, 10 Jun 2019 15:41:09 -0700
Subject: Fixed bug 4628 - SEGV_UNKNOW in function SDL_free_REAL at
SDL_malloc.c:5372-5
The PCX format specifies pcxh.BytesPerLine, which represents the size of a
single plane's scanline in bytes. Valid PCX images should have
pcxh.BytesPerLine >= surface->pitch.
pcxh.BytesPerLine and surface->pitch can legitimately be different because
pcxh.BytesPerLine is padded to be a multiple of machine word length (where
file was created).
If src_bits == 8 we directly read a whole scanline from src to row. This is
a problem in the case where bpl > surface->pitch because row is too small.
This allows attacker to perform unlimited OOB write on the heap.
+ remove pointless check bpl > surface->pitch, this is a valid situation
+ make sure we always read into buf which is big enough
+ in the case where src_bits == 8: copy these bytes back to row afterwar
Bug: https://security-tracker.debian.org/tracker/CVE-2019-12217
Bug: https://security-tracker.debian.org/tracker/CVE-2019-12219
Bug: https://security-tracker.debian.org/tracker/CVE-2019-12220
Bug: https://security-tracker.debian.org/tracker/CVE-2019-12221
Bug: https://security-tracker.debian.org/tracker/CVE-2019-12222
Origin: upstream, 2.0.5, commit:e7e9786a1a34, commit:https://github.com/libsdl-org/SDL_image/commit/1559b5ce67e25c8de65f0d4af020c1ec50cb7b85
Co-authored-by: Hugo Lefeuvre
---
IMG_pcx.c | 23 ++++++++++++++---------
1 file changed, 14 insertions(+), 9 deletions(-)
diff --git a/IMG_pcx.c b/IMG_pcx.c
index 0116f17..99af3f5 100644
--- a/IMG_pcx.c
+++ b/IMG_pcx.c
@@ -148,18 +148,17 @@ SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src)
goto done;
bpl = pcxh.NPlanes * pcxh.BytesPerLine;
- if (bpl < 0 || bpl > surface->pitch) {
- error = "bytes per line is too large (corrupt?)";
+ buf = (Uint8 *)SDL_calloc(bpl, 1);
+ if ( !buf ) {
+ error = "Out of memory";
goto done;
}
- buf = (Uint8 *)SDL_calloc(surface->pitch, 1);
row = surface->pixels;
for ( y=0; y<surface->h; ++y ) {
/* decode a scan line to a temporary buffer first */
int i;
- Uint8 *dst = buf;
if ( pcxh.Encoding == 0 ) {
- if(!SDL_RWread(src, dst, bpl, 1)) {
+ if(!SDL_RWread(src, buf, bpl, 1)) {
error = "file truncated";
goto done;
}
@@ -180,7 +179,7 @@ SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src)
}
}
}
- dst[i] = ch;
+ buf[i] = ch;
count--;
}
}
@@ -202,13 +201,21 @@ SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src)
}
}
}
+ } else if ( src_bits == 8 ) {
+ /* directly copy buf content to row */
+ Uint8 *innerSrc = buf;
+ int x;
+ Uint8 *dst = row;
+ for ( x = 0; x < width; x++ ) {
+ *dst++ = *innerSrc++;
+ }
} else if(src_bits == 24) {
/* de-interlace planes */
Uint8 *src = 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++) {
if ( dst >= row+surface->pitch ) {
error = "decoding out of bounds (corrupt?)";
@@ -218,8 +225,6 @@ SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src)
dst += pcxh.NPlanes;
}
}
- } else {
- SDL_memcpy(row, buf, bpl);
}
row += surface->pitch;
|