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

Reply via email to