dca: prevent accessing static arrays with invalid indexes.

Message ID 20120307174124.DB8365E0C2@aruru.libav.org
State New
Headers show

Commit Message

Janne Grunau March 7, 2012, 5:41 p.m.
Module: libav
Branch: master
Commit: e6ffd997cbc06426e75d3fa291b991866c84a79b

Author:    Ronald S. Bultje <rsbultje@gmail.com>
Committer: Ronald S. Bultje <rsbultje@gmail.com>
Date:      Tue Feb 28 18:11:59 2012 -0800

dca: prevent accessing static arrays with invalid indexes.

Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind
CC: libav-stable@libav.org

---

 libavcodec/dca.c     |   37 ++++++++++++++++++++++++++-----------
 libavcodec/dcadata.h |    2 +-
 2 files changed, 27 insertions(+), 12 deletions(-)

Patch

diff --git a/libavcodec/dca.c b/libavcodec/dca.c
index 71c1800..6dbcda0 100644
--- a/libavcodec/dca.c
+++ b/libavcodec/dca.c
@@ -640,13 +640,20 @@  static int dca_parse_frame_header(DCAContext *s)
 }
 
 
-static inline int get_scale(GetBitContext *gb, int level, int value)
+static inline int get_scale(GetBitContext *gb, int level, int value, int log2range)
 {
     if (level < 5) {
         /* huffman encoded */
         value += get_bitalloc(gb, &dca_scalefactor, level);
-    } else if (level < 8)
-        value = get_bits(gb, level + 1);
+        value = av_clip_uintp2(value, log2range);
+    } else if (level < 8) {
+        if (level + 1 > log2range) {
+            skip_bits(gb, level + 1 - log2range);
+            value = get_bits(gb, log2range);
+        } else {
+            value = get_bits(gb, level + 1);
+        }
+    }
     return value;
 }
 
@@ -719,28 +726,31 @@  static int dca_subframe_header(DCAContext *s, int base_channel, int block_index)
 
     for (j = base_channel; j < s->prim_channels; j++) {
         const uint32_t *scale_table;
-        int scale_sum;
+        int scale_sum, log_size;
 
         memset(s->scale_factor[j], 0,
                s->subband_activity[j] * sizeof(s->scale_factor[0][0][0]) * 2);
 
-        if (s->scalefactor_huffman[j] == 6)
+        if (s->scalefactor_huffman[j] == 6) {
             scale_table = scale_factor_quant7;
-        else
+            log_size = 7;
+        } else {
             scale_table = scale_factor_quant6;
+            log_size = 6;
+        }
 
         /* When huffman coded, only the difference is encoded */
         scale_sum = 0;
 
         for (k = 0; k < s->subband_activity[j]; k++) {
             if (k >= s->vq_start_subband[j] || s->bitalloc[j][k] > 0) {
-                scale_sum = get_scale(&s->gb, s->scalefactor_huffman[j], scale_sum);
+                scale_sum = get_scale(&s->gb, s->scalefactor_huffman[j], scale_sum, log_size);
                 s->scale_factor[j][k][0] = scale_table[scale_sum];
             }
 
             if (k < s->vq_start_subband[j] && s->transition_mode[j][k]) {
                 /* Get second scale factor */
-                scale_sum = get_scale(&s->gb, s->scalefactor_huffman[j], scale_sum);
+                scale_sum = get_scale(&s->gb, s->scalefactor_huffman[j], scale_sum, log_size);
                 s->scale_factor[j][k][1] = scale_table[scale_sum];
             }
         }
@@ -769,8 +779,7 @@  static int dca_subframe_header(DCAContext *s, int base_channel, int block_index)
              * (is this valid as well for joint scales ???) */
 
             for (k = s->subband_activity[j]; k < s->subband_activity[source_channel]; k++) {
-                scale = get_scale(&s->gb, s->joint_huff[j], 0);
-                scale += 64;    /* bias */
+                scale = get_scale(&s->gb, s->joint_huff[j], 64 /* bias */, 7);
                 s->joint_scale_factor[j][k] = scale;    /*joint_scale_table[scale]; */
             }
 
@@ -791,6 +800,11 @@  static int dca_subframe_header(DCAContext *s, int base_channel, int block_index)
             }
         } else {
             int am = s->amode & DCA_CHANNEL_MASK;
+            if (am >= FF_ARRAY_ELEMS(dca_default_coeffs)) {
+                av_log(s->avctx, AV_LOG_ERROR,
+                       "Invalid channel mode %d\n", am);
+                return AVERROR_INVALIDDATA;
+            }
             for (j = base_channel; j < s->prim_channels; j++) {
                 s->downmix_coef[j][0] = dca_default_coeffs[am][j][0];
                 s->downmix_coef[j][1] = dca_default_coeffs[am][j][1];
@@ -830,7 +844,8 @@  static int dca_subframe_header(DCAContext *s, int base_channel, int block_index)
         }
 
         /* Scale factor index */
-        s->lfe_scale_factor = scale_factor_quant7[get_bits(&s->gb, 8)];
+        skip_bits(&s->gb, 1);
+        s->lfe_scale_factor = scale_factor_quant7[get_bits(&s->gb, 7)];
 
         /* Quantization step size * scale factor */
         lfe_scale = 0.035 * s->lfe_scale_factor;
diff --git a/libavcodec/dcadata.h b/libavcodec/dcadata.h
index 0a83cdf..4b58ef7 100644
--- a/libavcodec/dcadata.h
+++ b/libavcodec/dcadata.h
@@ -7528,7 +7528,7 @@  static const float dca_downmix_coeffs[65] = {
   0.001412537544623, 0.001000000000000, 0.000501187233627, 0.000251188643151, 0.000000000000000,
 };
 
-static const uint8_t dca_default_coeffs[16][5][2] = {
+static const uint8_t dca_default_coeffs[10][5][2] = {
     { { 13, 13 },                                                 },
     { {  0, 64 }, { 64,  0 },                                     },
     { {  0, 64 }, { 64,  0 },                                     },