Skip to content

Commit a79b65c

Browse files
committed
Catch SGI buffer overruns
1 parent 93b22b8 commit a79b65c

File tree

4 files changed

+19
-6
lines changed

4 files changed

+19
-6
lines changed

Diff for: Tests/images/sgi_overrun_expandrow.bin

545 Bytes
Binary file not shown.

Diff for: Tests/images/sgi_overrun_expandrow2.bin

545 Bytes
Binary file not shown.

Diff for: Tests/test_image.py

+2
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,8 @@ def test_overrun(self):
593593
for file in [
594594
"fli_overrun.bin",
595595
"sgi_overrun.bin",
596+
"sgi_overrun_expandrow.bin",
597+
"sgi_overrun_expandrow2.bin",
596598
"pcx_overrun.bin",
597599
"pcx_overrun2.bin",
598600
]:

Diff for: src/libImaging/SgiRleDecode.c

+17-6
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ static void read4B(UINT32* dest, UINT8* buf)
2525
*dest = (UINT32)((buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]);
2626
}
2727

28-
static int expandrow(UINT8* dest, UINT8* src, int n, int z)
28+
static int expandrow(UINT8* dest, UINT8* src, int n, int z, int xsize)
2929
{
3030
UINT8 pixel, count;
3131

@@ -37,6 +37,9 @@ static int expandrow(UINT8* dest, UINT8* src, int n, int z)
3737
count = pixel & RLE_MAX_RUN;
3838
if (!count)
3939
return count;
40+
if (count > xsize) {
41+
return -1;
42+
}
4043
if (pixel & RLE_COPY_FLAG) {
4144
while(count--) {
4245
*dest = *src++;
@@ -56,7 +59,7 @@ static int expandrow(UINT8* dest, UINT8* src, int n, int z)
5659
return 0;
5760
}
5861

59-
static int expandrow2(UINT8* dest, const UINT8* src, int n, int z)
62+
static int expandrow2(UINT8* dest, const UINT8* src, int n, int z, int xsize)
6063
{
6164
UINT8 pixel, count;
6265

@@ -70,6 +73,9 @@ static int expandrow2(UINT8* dest, const UINT8* src, int n, int z)
7073
count = pixel & RLE_MAX_RUN;
7174
if (!count)
7275
return count;
76+
if (count > xsize) {
77+
return -1;
78+
}
7379
if (pixel & RLE_COPY_FLAG) {
7480
while(count--) {
7581
memcpy(dest, src, 2);
@@ -96,6 +102,7 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
96102
UINT8 *ptr;
97103
SGISTATE *c;
98104
int err = 0;
105+
int status;
99106

100107
/* Get all data from File descriptor */
101108
c = (SGISTATE*)state->context;
@@ -164,12 +171,16 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
164171

165172
/* row decompression */
166173
if (c->bpc ==1) {
167-
if(expandrow(&state->buffer[c->channo], &ptr[c->rleoffset], c->rlelength, im->bands))
168-
goto sgi_finish_decode;
174+
status = expandrow(&state->buffer[c->channo], &ptr[c->rleoffset], c->rlelength, im->bands, im->xsize);
169175
}
170176
else {
171-
if(expandrow2(&state->buffer[c->channo * 2], &ptr[c->rleoffset], c->rlelength, im->bands))
172-
goto sgi_finish_decode;
177+
status = expandrow2(&state->buffer[c->channo * 2], &ptr[c->rleoffset], c->rlelength, im->bands, im->xsize);
178+
}
179+
if (status == -1) {
180+
state->errcode = IMAGING_CODEC_OVERRUN;
181+
return -1;
182+
} else if (status == 1) {
183+
goto sgi_finish_decode;
173184
}
174185

175186
state->count += c->rlelength;

0 commit comments

Comments
 (0)