Fixed literal expansion, allowed run length > line length

This commit is contained in:
wiredfool 2016-11-19 17:39:30 -08:00
parent 17d38d0905
commit 5df2851f85

View File

@ -7,7 +7,7 @@
* decoder for SUN RLE data. * decoder for SUN RLE data.
* *
* history: * history:
* 97-01-04 fl Created * 97-01-04 fl Created
* *
* Copyright (c) Fredrik Lundh 1997. * Copyright (c) Fredrik Lundh 1997.
* Copyright (c) Secret Labs AB 1997. * Copyright (c) Secret Labs AB 1997.
@ -24,88 +24,106 @@ ImagingSunRleDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
{ {
int n; int n;
UINT8* ptr; UINT8* ptr;
UINT8 extra_data = 0;
UINT8 extra_bytes = 0;
int ct_bytes = 0;
ptr = buf; ptr = buf;
for (;;) { for (;;) {
if (bytes < 1) if (bytes < 1)
return ptr - buf; return ptr - buf;
if (ptr[0] == 0x80) { if (ptr[0] == 0x80) {
if (bytes < 2) if (bytes < 2)
break; break;
n = ptr[1]; n = ptr[1];
if (n == 0) {
/* Literal 0x80 (2 bytes) */ if (n == 0) {
n = 1;
state->buffer[state->x] = 0x80; /* Literal 0x80 (2 bytes) */
n = 1;
ct_bytes += n;
ptr += 2; state->buffer[state->x] = 0x80;
bytes -= 2;
} else { ptr += 2;
bytes -= 2;
/* Run (3 bytes) */ } else {
if (bytes < 3)
break;
if (state->x + n > state->bytes) { /* Run (3 bytes) */
/* FIXME: is this correct? */ if (bytes < 3)
state->errcode = IMAGING_CODEC_OVERRUN; break;
return -1;
}
memset(state->buffer + state->x, ptr[2], n); ct_bytes += n;
ptr += 3; if (state->x + n > state->bytes) {
bytes -= 3; extra_bytes = n; /* full value */
n = state->bytes - state->x;
extra_bytes -= n;
extra_data = ptr[2];
}
} memset(state->buffer + state->x, ptr[2], n);
} else { ptr += 3;
bytes -= 3;
/* Literal (1+n bytes block) */ }
n = ptr[0];
if (bytes < 1 + n) } else {
break;
if (state->x + n > state->bytes) { /* Literal byte */
/* FIXME: is this correct? */ n = 1;
state->errcode = IMAGING_CODEC_OVERRUN; ct_bytes += n;
return -1;
}
memcpy(state->buffer + state->x, ptr + 1, n); state->buffer[state->x] = ptr[0];
ptr += 1 + n; ptr += 1;
bytes -= 1 + n; bytes -= 1;
} }
state->x += n; for (;;) {
state->x += n;
if (state->x >= state->bytes) {
if (state->x >= state->bytes) { /* Got a full line, unpack it */
state->shuffle((UINT8*) im->image[state->y + state->yoff] +
state->xoff * im->pixelsize, state->buffer,
state->xsize);
/* Got a full line, unpack it */ state->x = 0;
state->shuffle((UINT8*) im->image[state->y + state->yoff] +
state->xoff * im->pixelsize, state->buffer,
state->xsize);
state->x = 0; if (++state->y >= state->ysize) {
/* End of file (errcode = 0) */
printf("%d", ct_bytes);
return -1;
}
}
if (extra_bytes == 0) {
break;
}
if (++state->y >= state->ysize) { if (state->x > 0) {
/* End of file (errcode = 0) */ break; // assert
return -1; }
}
}
if (extra_bytes >= state->bytes) {
n = state->bytes;
} else {
n = extra_bytes;
}
memset(state->buffer + state->x, extra_data, n);
extra_bytes -= n;
}
} }
return ptr - buf; return ptr - buf;