[libav-devel] [PATCH 2/8] rpza: Check the blocks left before processing one

Luca Barbato lu_zero at gentoo.org
Sun Nov 1 04:07:42 CET 2015


Bug-Id: 903
CC: libav-stable at libav.org
Reported-By: Mateusz "j00ru" Jurczyk and Gynvael Coldwind
---
 libavcodec/rpza.c | 52 +++++++++++++++++++++++++++++++---------------------
 1 file changed, 31 insertions(+), 21 deletions(-)

diff --git a/libavcodec/rpza.c b/libavcodec/rpza.c
index f365a06..d1c959d 100644
--- a/libavcodec/rpza.c
+++ b/libavcodec/rpza.c
@@ -52,23 +52,25 @@ typedef struct RpzaContext {
     GetByteContext gb;
 } RpzaContext;
 
-#define ADVANCE_BLOCK() \
-{ \
-    pixel_ptr += 4; \
-    if (pixel_ptr >= width) \
-    { \
-        pixel_ptr = 0; \
-        row_ptr += stride * 4; \
-    } \
-    total_blocks--; \
-    if (total_blocks < 0) \
-    { \
-        av_log(s->avctx, AV_LOG_ERROR, "warning: block counter just went negative (this should not happen)\n"); \
-        return; \
-    } \
-}
+#define CHECK_BLOCK()                                                         \
+    if (total_blocks < 1) {                                                    \
+        av_log(s->avctx, AV_LOG_ERROR,                                         \
+               "Block counter just went negative (this should not happen)\n"); \
+        return AVERROR_INVALIDDATA;                                            \
+    }                                                                          \
+
+#define ADVANCE_BLOCK()             \
+    {                               \
+        pixel_ptr += 4;             \
+        if (pixel_ptr >= width)     \
+        {                           \
+            pixel_ptr = 0;          \
+            row_ptr  += stride * 4; \
+        }                           \
+        total_blocks--;             \
+    }
 
-static void rpza_decode_stream(RpzaContext *s)
+static int rpza_decode_stream(RpzaContext *s)
 {
     int width = s->avctx->width;
     int stride = s->frame->linesize[0] / 2;
@@ -126,7 +128,8 @@ static void rpza_decode_stream(RpzaContext *s)
         /* Skip blocks */
         case 0x80:
             while (n_blocks--) {
-              ADVANCE_BLOCK();
+                CHECK_BLOCK();
+                ADVANCE_BLOCK();
             }
             break;
 
@@ -134,6 +137,7 @@ static void rpza_decode_stream(RpzaContext *s)
         case 0xa0:
             colorA = bytestream2_get_be16(&s->gb);
             while (n_blocks--) {
+                CHECK_BLOCK();
                 block_ptr = row_ptr + pixel_ptr;
                 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
                     for (pixel_x = 0; pixel_x < 4; pixel_x++){
@@ -177,8 +181,9 @@ static void rpza_decode_stream(RpzaContext *s)
             color4[2] |= ((21 * ta + 11 * tb) >> 5);
 
             if (bytestream2_get_bytes_left(&s->gb) < n_blocks * 4)
-                return;
+                return AVERROR_INVALIDDATA;
             while (n_blocks--) {
+                CHECK_BLOCK();
                 block_ptr = row_ptr + pixel_ptr;
                 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
                     uint8_t index = bytestream2_get_byteu(&s->gb);
@@ -196,7 +201,8 @@ static void rpza_decode_stream(RpzaContext *s)
         /* Fill block with 16 colors */
         case 0x00:
             if (bytestream2_get_bytes_left(&s->gb) < 30)
-                return;
+                return AVERROR_INVALIDDATA;
+            CHECK_BLOCK();
             block_ptr = row_ptr + pixel_ptr;
             for (pixel_y = 0; pixel_y < 4; pixel_y++) {
                 for (pixel_x = 0; pixel_x < 4; pixel_x++){
@@ -216,9 +222,11 @@ static void rpza_decode_stream(RpzaContext *s)
             av_log(s->avctx, AV_LOG_ERROR, "Unknown opcode %d in rpza chunk."
                  " Skip remaining %d bytes of chunk data.\n", opcode,
                  bytestream2_get_bytes_left(&s->gb));
-            return;
+            return AVERROR_INVALIDDATA;
         } /* Opcode switch */
     }
+
+    return 0;
 }
 
 static av_cold int rpza_decode_init(AVCodecContext *avctx)
@@ -249,7 +257,9 @@ static int rpza_decode_frame(AVCodecContext *avctx,
         return ret;
     }
 
-    rpza_decode_stream(s);
+    ret = rpza_decode_stream(s);
+    if (ret < 0)
+        return ret;
 
     if ((ret = av_frame_ref(data, s->frame)) < 0)
         return ret;
-- 
2.6.2.402.g2635c2b.dirty



More information about the libav-devel mailing list