stream_ptr would go over the buffer limit and cause invalid reads
Fixes bugzilla #156
---
libavcodec/flicvideo.c | 24 ++++++++++++++++++++++++
1 files changed, 24 insertions(+), 0 deletions(-)
diff --git a/libavcodec/flicvideo.c b/libavcodec/flicvideo.c
index 8e8a813..c39df79 100644
--- a/libavcodec/flicvideo.c
+++ b/libavcodec/flicvideo.c
@@ -66,6 +66,12 @@
return -1; \
} \
+#define CHECK_STREAM_PTR(n) \
+ if (stream_ptr + n > buf_size) { \
+ av_log(s->avctx, AV_LOG_INFO, "Problem: stream_ptr >= buf_size (%d >=
%d)\n", stream_ptr + n, buf_size); \
+ return -1; \
+ } \
+
typedef struct FlicDecodeContext {
AVCodecContext *avctx;
AVFrame frame;
@@ -182,6 +188,7 @@ static int flic_decode_frame_8BPP(AVCodecContext *avctx,
/* iterate through the chunks */
while ((frame_size > 0) && (num_chunks > 0)) {
+ CHECK_STREAM_PTR(6);
chunk_size = AV_RL32(&buf[stream_ptr]);
stream_ptr += 4;
chunk_type = AV_RL16(&buf[stream_ptr]);
@@ -205,6 +212,8 @@ static int flic_decode_frame_8BPP(AVCodecContext *avctx,
stream_ptr += 2;
palette_ptr = 0;
for (i = 0; i < color_packets; i++) {
+ CHECK_STREAM_PTR(2);
+
/* first byte is how many colors to skip */
palette_ptr += buf[stream_ptr++];
@@ -215,6 +224,7 @@ static int flic_decode_frame_8BPP(AVCodecContext *avctx,
if (color_changes == 0)
color_changes = 256;
+ CHECK_STREAM_PTR(3 * color_changes);
for (j = 0; j < color_changes; j++) {
unsigned int entry;
@@ -245,6 +255,7 @@ static int flic_decode_frame_8BPP(AVCodecContext *avctx,
compressed_lines = AV_RL16(&buf[stream_ptr]);
stream_ptr += 2;
while (compressed_lines > 0) {
+ CHECK_STREAM_PTR(0);
line_packets = AV_RL16(&buf[stream_ptr]);
stream_ptr += 2;
if ((line_packets & 0xC000) == 0xC000) {
@@ -265,12 +276,15 @@ static int flic_decode_frame_8BPP(AVCodecContext *avctx,
pixel_countdown = s->avctx->width;
for (i = 0; i < line_packets; i++) {
/* account for the skip bytes */
+ CHECK_STREAM_PTR(2);
pixel_skip = buf[stream_ptr++];
pixel_ptr += pixel_skip;
pixel_countdown -= pixel_skip;
byte_run = (signed char)(buf[stream_ptr++]);
if (byte_run < 0) {
byte_run = -byte_run;
+
+ CHECK_STREAM_PTR(2);
palette_idx1 = buf[stream_ptr++];
palette_idx2 = buf[stream_ptr++];
CHECK_PIXEL_PTR(byte_run * 2);
@@ -279,6 +293,7 @@ static int flic_decode_frame_8BPP(AVCodecContext *avctx,
pixels[pixel_ptr++] = palette_idx2;
}
} else {
+ CHECK_STREAM_PTR(byte_run * 2);
CHECK_PIXEL_PTR(byte_run * 2);
for (j = 0; j < byte_run * 2; j++,
pixel_countdown--) {
palette_idx1 = buf[stream_ptr++];
@@ -388,6 +403,7 @@ static int flic_decode_frame_8BPP(AVCodecContext *avctx,
"bigger than image, skipping chunk\n", chunk_size - 6);
stream_ptr += chunk_size - 6;
} else {
+ CHECK_STREAM_PTR(s->frame.linesize[0] * s->avctx->height *
s->avctx->width);
for (y_ptr = 0; y_ptr < s->frame.linesize[0] *
s->avctx->height;
y_ptr += s->frame.linesize[0]) {
memcpy(&pixels[y_ptr], &buf[stream_ptr],
@@ -480,6 +496,7 @@ static int flic_decode_frame_15_16BPP(AVCodecContext *avctx,
/* iterate through the chunks */
while ((frame_size > 0) && (num_chunks > 0)) {
+ CHECK_STREAM_PTR(6);
chunk_size = AV_RL32(&buf[stream_ptr]);
stream_ptr += 4;
chunk_type = AV_RL16(&buf[stream_ptr]);
@@ -501,6 +518,7 @@ static int flic_decode_frame_15_16BPP(AVCodecContext *avctx,
compressed_lines = AV_RL16(&buf[stream_ptr]);
stream_ptr += 2;
while (compressed_lines > 0) {
+ CHECK_STREAM_PTR(0);
line_packets = AV_RL16(&buf[stream_ptr]);
stream_ptr += 2;
if (line_packets < 0) {
@@ -513,6 +531,7 @@ static int flic_decode_frame_15_16BPP(AVCodecContext *avctx,
pixel_countdown = s->avctx->width;
for (i = 0; i < line_packets; i++) {
/* account for the skip bytes */
+ CHECK_STREAM_PTR(2);
pixel_skip = buf[stream_ptr++];
pixel_ptr += (pixel_skip*2); /* Pixel is 2 bytes wide
*/
pixel_countdown -= pixel_skip;
@@ -528,6 +547,7 @@ static int flic_decode_frame_15_16BPP(AVCodecContext *avctx,
}
} else {
CHECK_PIXEL_PTR(2 * byte_run);
+ CHECK_STREAM_PTR(2 * byte_run);
for (j = 0; j < byte_run; j++, pixel_countdown--) {
*((signed short*)(&pixels[pixel_ptr])) =
AV_RL16(&buf[stream_ptr]);
stream_ptr += 2;
@@ -562,6 +582,7 @@ static int flic_decode_frame_15_16BPP(AVCodecContext *avctx,
pixel_countdown = (s->avctx->width * 2);
while (pixel_countdown > 0) {
+ CHECK_STREAM_PTR(0);
byte_run = (signed char)(buf[stream_ptr++]);
if (byte_run > 0) {
palette_idx1 = buf[stream_ptr++];
@@ -576,6 +597,7 @@ static int flic_decode_frame_15_16BPP(AVCodecContext *avctx,
} else { /* copy bytes if byte_run < 0 */
byte_run = -byte_run;
CHECK_PIXEL_PTR(byte_run);
+ CHECK_STREAM_PTR(byte_run);
for (j = 0; j < byte_run; j++) {
palette_idx1 = buf[stream_ptr++];
pixels[pixel_ptr++] = palette_idx1;
@@ -630,6 +652,7 @@ static int flic_decode_frame_15_16BPP(AVCodecContext *avctx,
} else { /* copy pixels if byte_run < 0 */
byte_run = -byte_run;
CHECK_PIXEL_PTR(2 * byte_run);
+ CHECK_STREAM_PTR(2 * byte_run);
for (j = 0; j < byte_run; j++) {
*((signed short*)(&pixels[pixel_ptr])) =
AV_RL16(&buf[stream_ptr]);
stream_ptr += 2;
@@ -661,6 +684,7 @@ static int flic_decode_frame_15_16BPP(AVCodecContext *avctx,
pixel_countdown = s->avctx->width;
pixel_ptr = 0;
while (pixel_countdown > 0) {
+ CHECK_STREAM_PTR(pixel_ptr);
*((signed short*)(&pixels[y_ptr + pixel_ptr])) =
AV_RL16(&buf[stream_ptr+pixel_ptr]);
pixel_ptr += 2;
pixel_countdown--;
--
1.7.5.4
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel