Skip to content

Commit ee60e60

Browse files
committed
Fixed bug 4628 - SEGV_UNKNOW in function SDL_free_REAL at SDL_malloc.c:5372-5
Hugo Lefeuvre 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
1 parent a1f2a0d commit ee60e60

File tree

1 file changed

+16
-10
lines changed

1 file changed

+16
-10
lines changed

IMG_pcx.c

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -156,22 +156,22 @@ SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src)
156156
}
157157
surface = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height,
158158
bits, Rmask, Gmask, Bmask, Amask);
159-
if ( surface == NULL )
159+
if ( surface == NULL ) {
160160
goto done;
161+
}
161162

162163
bpl = pcxh.NPlanes * pcxh.BytesPerLine;
163-
if ( bpl < 0 || bpl > surface->pitch ) {
164-
error = "bytes per line is too large (corrupt?)";
164+
buf = (Uint8 *)SDL_calloc(bpl, 1);
165+
if ( !buf ) {
166+
error = "Out of memory";
165167
goto done;
166168
}
167-
buf = (Uint8 *)SDL_calloc(surface->pitch, 1);
168169
row = (Uint8 *)surface->pixels;
169170
for ( y=0; y<surface->h; ++y ) {
170171
/* decode a scan line to a temporary buffer first */
171172
int i;
172-
Uint8 *dst = buf;
173173
if ( pcxh.Encoding == 0 ) {
174-
if ( !SDL_RWread(src, dst, bpl, 1) ) {
174+
if ( !SDL_RWread(src, buf, bpl, 1) ) {
175175
error = "file truncated";
176176
goto done;
177177
}
@@ -192,7 +192,7 @@ SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src)
192192
}
193193
}
194194
}
195-
dst[i] = ch;
195+
buf[i] = ch;
196196
count--;
197197
}
198198
}
@@ -214,13 +214,21 @@ SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src)
214214
}
215215
}
216216
}
217+
} else if ( src_bits == 8 ) {
218+
/* directly copy buf content to row */
219+
Uint8 *innerSrc = buf;
220+
int x;
221+
Uint8 *dst = row;
222+
for ( x = 0; x < width; x++ ) {
223+
*dst++ = *innerSrc++;
224+
}
217225
} else if ( src_bits == 24 ) {
218226
/* de-interlace planes */
219227
Uint8 *innerSrc = buf;
220228
int plane;
221229
for ( plane = 0; plane < pcxh.NPlanes; plane++ ) {
222230
int x;
223-
dst = row + plane;
231+
Uint8 *dst = row + plane;
224232
for ( x = 0; x < width; x++ ) {
225233
if ( dst >= row+surface->pitch ) {
226234
error = "decoding out of bounds (corrupt?)";
@@ -230,8 +238,6 @@ SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src)
230238
dst += pcxh.NPlanes;
231239
}
232240
}
233-
} else {
234-
SDL_memcpy(row, buf, bpl);
235241
}
236242

237243
row += surface->pitch;

0 commit comments

Comments
 (0)