[libav-stable] wavpack: use bytestream2 in wavpack_decode_block

Luca Barbato git at libav.org
Wed May 22 22:02:36 CEST 2013


Module: libav
Branch: master
Commit: 3f0b6d7a6248a33df37b98cfcb37a1acce263f62

Author:    Luca Barbato <lu_zero at gentoo.org>
Committer: Luca Barbato <lu_zero at gentoo.org>
Date:      Wed May 22 12:27:04 2013 +0200

wavpack: use bytestream2 in wavpack_decode_block

Prevent most out of buffer reads.

Reported-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind
CC: libav-stable at libav.org

---

 libavcodec/wavpack.c |  166 +++++++++++++++++++++++++-------------------------
 1 files changed, 83 insertions(+), 83 deletions(-)

diff --git a/libavcodec/wavpack.c b/libavcodec/wavpack.c
index 8d7c82b..cfcd22d 100644
--- a/libavcodec/wavpack.c
+++ b/libavcodec/wavpack.c
@@ -26,6 +26,7 @@
 #include "get_bits.h"
 #include "internal.h"
 #include "unary.h"
+#include "bytestream.h"
 
 /**
  * @file
@@ -761,12 +762,11 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no,
 {
     WavpackContext *wc = avctx->priv_data;
     WavpackFrameContext *s;
+    GetByteContext gb;
     void *samples = data;
     int samplecount;
     int got_terms   = 0, got_weights = 0, got_samples = 0,
         got_entropy = 0, got_bs      = 0, got_float   = 0, got_hybrid = 0;
-    const uint8_t *orig_buf = buf;
-    const uint8_t *buf_end  = buf + buf_size;
     int i, j, id, size, ssize, weights, t;
     int bpp, chan, chmask, orig_bpp;
 
@@ -793,9 +793,10 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no,
     s->and            = s->or = s->shift = 0;
     s->got_extra_bits = 0;
 
+    bytestream2_init(&gb, buf, buf_size);
+
     if (!wc->mkv_mode) {
-        s->samples = AV_RL32(buf);
-        buf       += 4;
+        s->samples = bytestream2_get_le32(&gb);
         if (s->samples != wc->samples)
             return AVERROR_INVALIDDATA;
 
@@ -806,8 +807,7 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no,
     } else {
         s->samples = wc->samples;
     }
-    s->frame_flags = AV_RL32(buf);
-    buf           += 4;
+    s->frame_flags = bytestream2_get_le32(&gb);
     bpp            = av_get_bytes_per_sample(avctx->sample_fmt);
     samples        = (uint8_t *)samples + bpp * wc->ch_offset;
     orig_bpp       = ((s->frame_flags & 0x03) + 1) << 3;
@@ -820,20 +820,20 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no,
     s->post_shift     = bpp * 8 - orig_bpp + ((s->frame_flags >> 13) & 0x1f);
     s->hybrid_maxclip =  ((1LL << (orig_bpp - 1)) - 1);
     s->hybrid_minclip = ((-1LL << (orig_bpp - 1)));
-    s->CRC            = AV_RL32(buf);
-    buf              += 4;
+    s->CRC            = bytestream2_get_le32(&gb);
+
     if (wc->mkv_mode)
-        buf += 4;  // skip block size;
+        bytestream2_skip(&gb, 4);  // skip block size;
 
     wc->ch_offset += 1 + s->stereo;
 
     // parse metadata blocks
-    while (buf < buf_end) {
-        id   = *buf++;
-        size = *buf++;
+    while (bytestream2_get_bytes_left(&gb)) {
+        id   = bytestream2_get_byte(&gb);
+        size = bytestream2_get_byte(&gb);
         if (id & WP_IDF_LONG) {
-            size |= (*buf++) << 8;
-            size |= (*buf++) << 16;
+            size |= (bytestream2_get_byte(&gb)) << 8;
+            size |= (bytestream2_get_byte(&gb)) << 16;
         }
         size <<= 1; // size is specified in words
         ssize  = size;
@@ -844,13 +844,13 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no,
                    "Got incorrect block %02X with size %i\n", id, size);
             break;
         }
-        if (buf + ssize > buf_end) {
+        if (bytestream2_get_bytes_left(&gb) < ssize) {
             av_log(avctx, AV_LOG_ERROR,
                    "Block size %i is out of bounds\n", size);
             break;
         }
         if (id & WP_IDF_IGNORE) {
-            buf += ssize;
+            bytestream2_skip(&gb, ssize);
             continue;
         }
         switch (id & WP_IDF_MASK) {
@@ -858,14 +858,14 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no,
             if (size > MAX_TERMS) {
                 av_log(avctx, AV_LOG_ERROR, "Too many decorrelation terms\n");
                 s->terms = 0;
-                buf     += ssize;
+                bytestream2_skip(&gb, ssize);
                 continue;
             }
             s->terms = size;
             for (i = 0; i < s->terms; i++) {
-                s->decorr[s->terms - i - 1].value = (*buf & 0x1F) - 5;
-                s->decorr[s->terms - i - 1].delta = *buf >> 5;
-                buf++;
+                uint8_t val = bytestream2_get_byte(&gb);
+                s->decorr[s->terms - i - 1].value = (val & 0x1F) - 5;
+                s->decorr[s->terms - i - 1].delta =  val >> 5;
             }
             got_terms = 1;
             break;
@@ -877,17 +877,17 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no,
             weights = size >> s->stereo_in;
             if (weights > MAX_TERMS || weights > s->terms) {
                 av_log(avctx, AV_LOG_ERROR, "Too many decorrelation weights\n");
-                buf += ssize;
+                bytestream2_skip(&gb, ssize);
                 continue;
             }
             for (i = 0; i < weights; i++) {
-                t                                   = (int8_t)(*buf++);
+                t = (int8_t)bytestream2_get_byte(&gb);
                 s->decorr[s->terms - i - 1].weightA = t << 3;
                 if (s->decorr[s->terms - i - 1].weightA > 0)
                     s->decorr[s->terms - i - 1].weightA +=
                         (s->decorr[s->terms - i - 1].weightA + 64) >> 7;
                 if (s->stereo_in) {
-                    t                                   = (int8_t)(*buf++);
+                    t = (int8_t)bytestream2_get_byte(&gb);
                     s->decorr[s->terms - i - 1].weightB = t << 3;
                     if (s->decorr[s->terms - i - 1].weightB > 0)
                         s->decorr[s->terms - i - 1].weightB +=
@@ -904,31 +904,32 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no,
             t = 0;
             for (i = s->terms - 1; (i >= 0) && (t < size); i--) {
                 if (s->decorr[i].value > 8) {
-                    s->decorr[i].samplesA[0] = wp_exp2(AV_RL16(buf));
-                    buf                     += 2;
-                    s->decorr[i].samplesA[1] = wp_exp2(AV_RL16(buf));
-                    buf                     += 2;
+                    s->decorr[i].samplesA[0] =
+                        wp_exp2(bytestream2_get_le16(&gb));
+                    s->decorr[i].samplesA[1] =
+                        wp_exp2(bytestream2_get_le16(&gb));
+
                     if (s->stereo_in) {
-                        s->decorr[i].samplesB[0] = wp_exp2(AV_RL16(buf));
-                        buf                     += 2;
-                        s->decorr[i].samplesB[1] = wp_exp2(AV_RL16(buf));
-                        buf                     += 2;
+                        s->decorr[i].samplesB[0] =
+                            wp_exp2(bytestream2_get_le16(&gb));
+                        s->decorr[i].samplesB[1] =
+                            wp_exp2(bytestream2_get_le16(&gb));
                         t                       += 4;
                     }
                     t += 4;
                 } else if (s->decorr[i].value < 0) {
-                    s->decorr[i].samplesA[0] = wp_exp2(AV_RL16(buf));
-                    buf                     += 2;
-                    s->decorr[i].samplesB[0] = wp_exp2(AV_RL16(buf));
-                    buf                     += 2;
+                    s->decorr[i].samplesA[0] =
+                        wp_exp2(bytestream2_get_le16(&gb));
+                    s->decorr[i].samplesB[0] =
+                        wp_exp2(bytestream2_get_le16(&gb));
                     t                       += 4;
                 } else {
                     for (j = 0; j < s->decorr[i].value; j++) {
-                        s->decorr[i].samplesA[j] = wp_exp2(AV_RL16(buf));
-                        buf                     += 2;
+                        s->decorr[i].samplesA[j] =
+                            wp_exp2(bytestream2_get_le16(&gb));
                         if (s->stereo_in) {
-                            s->decorr[i].samplesB[j] = wp_exp2(AV_RL16(buf));
-                            buf                     += 2;
+                            s->decorr[i].samplesB[j] =
+                                wp_exp2(bytestream2_get_le16(&gb));
                         }
                     }
                     t += s->decorr[i].value * 2 * (s->stereo_in + 1);
@@ -941,33 +942,30 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no,
                 av_log(avctx, AV_LOG_ERROR,
                        "Entropy vars size should be %i, got %i",
                        6 * (s->stereo_in + 1), size);
-                buf += ssize;
+                bytestream2_skip(&gb, ssize);
                 continue;
             }
             for (j = 0; j <= s->stereo_in; j++)
                 for (i = 0; i < 3; i++) {
-                    s->ch[j].median[i] = wp_exp2(AV_RL16(buf));
-                    buf               += 2;
+                    s->ch[j].median[i] = wp_exp2(bytestream2_get_le16(&gb));
                 }
             got_entropy = 1;
             break;
         case WP_ID_HYBRID:
             if (s->hybrid_bitrate) {
                 for (i = 0; i <= s->stereo_in; i++) {
-                    s->ch[i].slow_level = wp_exp2(AV_RL16(buf));
-                    buf                += 2;
+                    s->ch[i].slow_level = wp_exp2(bytestream2_get_le16(&gb));
                     size               -= 2;
                 }
             }
             for (i = 0; i < (s->stereo_in + 1); i++) {
-                s->ch[i].bitrate_acc = AV_RL16(buf) << 16;
-                buf                 += 2;
+                s->ch[i].bitrate_acc = bytestream2_get_le16(&gb) << 16;
                 size                -= 2;
             }
             if (size > 0) {
                 for (i = 0; i < (s->stereo_in + 1); i++) {
-                    s->ch[i].bitrate_delta = wp_exp2((int16_t)AV_RL16(buf));
-                    buf                   += 2;
+                    s->ch[i].bitrate_delta =
+                        wp_exp2((int16_t)bytestream2_get_le16(&gb));
                 }
             } else {
                 for (i = 0; i < (s->stereo_in + 1); i++)
@@ -975,24 +973,26 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no,
             }
             got_hybrid = 1;
             break;
-        case WP_ID_INT32INFO:
+        case WP_ID_INT32INFO: {
+            uint8_t val[4];
             if (size != 4) {
                 av_log(avctx, AV_LOG_ERROR,
-                       "Invalid INT32INFO, size = %i, sent_bits = %i\n",
-                       size, *buf);
-                buf += ssize;
+                       "Invalid INT32INFO, size = %i\n",
+                       size);
+                bytestream2_skip(&gb, ssize - 4);
                 continue;
             }
-            if (buf[0])
-                s->extra_bits = buf[0];
-            else if (buf[1])
-                s->shift = buf[1];
-            else if (buf[2]) {
+            bytestream2_get_buffer(&gb, val, 4);
+            if (val[0]) {
+                s->extra_bits = val[0];
+            } else if (val[1]) {
+                s->shift = val[1];
+            } else if (val[2]) {
                 s->and   = s->or = 1;
-                s->shift = buf[2];
-            } else if (buf[3]) {
+                s->shift = val[2];
+            } else if (val[3]) {
                 s->and   = 1;
-                s->shift = buf[3];
+                s->shift = val[3];
             }
             /* original WavPack decoder forces 32-bit lossy sound to be treated
              * as 24-bit one in order to have proper clipping */
@@ -1002,41 +1002,41 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no,
                 s->hybrid_maxclip >>= 8;
                 s->hybrid_minclip >>= 8;
             }
-            buf += 4;
             break;
+        }
         case WP_ID_FLOATINFO:
             if (size != 4) {
                 av_log(avctx, AV_LOG_ERROR,
                        "Invalid FLOATINFO, size = %i\n", size);
-                buf += ssize;
+                bytestream2_skip(&gb, ssize);
                 continue;
             }
-            s->float_flag    = buf[0];
-            s->float_shift   = buf[1];
-            s->float_max_exp = buf[2];
-            buf             += 4;
+            s->float_flag    = bytestream2_get_byte(&gb);
+            s->float_shift   = bytestream2_get_byte(&gb);
+            s->float_max_exp = bytestream2_get_byte(&gb);
             got_float        = 1;
+            bytestream2_skip(&gb, 1);
             break;
         case WP_ID_DATA:
-            s->sc.offset = buf - orig_buf;
+            s->sc.offset = bytestream2_tell(&gb);
             s->sc.size   = size * 8;
-            init_get_bits(&s->gb, buf, size * 8);
+            init_get_bits(&s->gb, gb.buffer, size * 8);
             s->data_size = size * 8;
-            buf         += size;
+            bytestream2_skip(&gb, size);
             got_bs       = 1;
             break;
         case WP_ID_EXTRABITS:
             if (size <= 4) {
                 av_log(avctx, AV_LOG_ERROR, "Invalid EXTRABITS, size = %i\n",
                        size);
-                buf += size;
+                bytestream2_skip(&gb, size);
                 continue;
             }
-            s->extra_sc.offset = buf - orig_buf;
+            s->extra_sc.offset = bytestream2_tell(&gb);
             s->extra_sc.size   = size * 8;
-            init_get_bits(&s->gb_extra_bits, buf, size * 8);
+            init_get_bits(&s->gb_extra_bits, gb.buffer, size * 8);
             s->crc_extra_bits  = get_bits_long(&s->gb_extra_bits, 32);
-            buf               += size;
+            bytestream2_skip(&gb, size);
             s->got_extra_bits  = 1;
             break;
         case WP_ID_CHANINFO:
@@ -1045,23 +1045,24 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no,
                        "Insufficient channel information\n");
                 return AVERROR_INVALIDDATA;
             }
-            chan = *buf++;
+            chan = bytestream2_get_byte(&gb);
             switch (size - 2) {
             case 0:
-                chmask = *buf;
+                chmask = bytestream2_get_byte(&gb);
                 break;
             case 1:
-                chmask = AV_RL16(buf);
+                chmask = bytestream2_get_le16(&gb);
                 break;
             case 2:
-                chmask = AV_RL24(buf);
+                chmask = bytestream2_get_le24(&gb);
                 break;
             case 3:
-                chmask = AV_RL32(buf);
+                chmask = bytestream2_get_le32(&gb);;
                 break;
             case 5:
-                chan  |= (buf[1] & 0xF) << 8;
-                chmask = AV_RL24(buf + 2);
+                bytestream2_skip(&gb, 1);
+                chan  |= (bytestream2_get_byte(&gb) & 0xF) << 8;
+                chmask = bytestream2_get_le16(&gb);
                 break;
             default:
                 av_log(avctx, AV_LOG_ERROR, "Invalid channel info size %d\n",
@@ -1078,13 +1079,12 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no,
             }
             if (!avctx->channel_layout)
                 avctx->channel_layout = chmask;
-            buf += size - 1;
             break;
         default:
-            buf += size;
+            bytestream2_skip(&gb, size);
         }
         if (id & WP_IDF_ODD)
-            buf++;
+            bytestream2_skip(&gb, 1);
     }
 
     if (!got_terms) {



More information about the libav-stable mailing list