diff mbox

[FFmpeg-devel,3/4] avcodec/vp568: Check that there is enough data for ff_vp56_init_range_decoder()

Message ID 20170307014143.19735-3-michael@niedermayer.cc
State Superseded
Headers show

Commit Message

Michael Niedermayer March 7, 2017, 1:41 a.m. UTC
Fixes: timeout in 730/clusterfuzz-testcase-5265113739165696

Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/targets/ffmpeg
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
---
 libavcodec/vp5.c     |  5 ++++-
 libavcodec/vp56.h    |  2 +-
 libavcodec/vp56rac.c |  5 ++++-
 libavcodec/vp6.c     | 15 +++++++++++----
 libavcodec/vp8.c     | 21 ++++++++++++++-------
 5 files changed, 34 insertions(+), 14 deletions(-)

Comments

Ronald S. Bultje March 7, 2017, 1:35 p.m. UTC | #1
Hi,

On Mon, Mar 6, 2017 at 8:41 PM, Michael Niedermayer <michael@niedermayer.cc>
wrote:

> -void ff_vp56_init_range_decoder(VP56RangeCoder *c, const uint8_t *buf,
> int buf_size)
> +int ff_vp56_init_range_decoder(VP56RangeCoder *c, const uint8_t *buf,
> int buf_size)
>  {
>      c->high = 255;
>      c->bits = -16;
>      c->buffer = buf;
>      c->end = buf + buf_size;
> +    if (buf_size < 1)
> +        return AVERROR_INVALIDDATA;
>      c->code_word = bytestream_get_be24(&c->buffer);
> +    return 0;
>  }


Isn't this AV_INPUT_BUFFER_PADDING_SIZE?

And this is inconsistent with the silent failure in renorm().

Ronald
Michael Niedermayer March 7, 2017, 5:01 p.m. UTC | #2
On Tue, Mar 07, 2017 at 08:35:33AM -0500, Ronald S. Bultje wrote:
> Hi,
> 
> On Mon, Mar 6, 2017 at 8:41 PM, Michael Niedermayer <michael@niedermayer.cc>
> wrote:
> 
> > -void ff_vp56_init_range_decoder(VP56RangeCoder *c, const uint8_t *buf,
> > int buf_size)
> > +int ff_vp56_init_range_decoder(VP56RangeCoder *c, const uint8_t *buf,
> > int buf_size)
> >  {
> >      c->high = 255;
> >      c->bits = -16;
> >      c->buffer = buf;
> >      c->end = buf + buf_size;
> > +    if (buf_size < 1)
> > +        return AVERROR_INVALIDDATA;
> >      c->code_word = bytestream_get_be24(&c->buffer);
> > +    return 0;
> >  }
> 
> 
> Isn't this AV_INPUT_BUFFER_PADDING_SIZE?

There was no out of array access, the issue was that the code spend
alot of time doing nothing as a result of 0 bytes input being turned
into 16bits of available data repeatly.

I intended to suggest to adjust the 16 to 8 on a 1 byte buf_size
subsequently

> 
> And this is inconsistent with the silent failure in renorm().

testing each use of renorm likely would cause a speed loss, such
a failure should be caught by the explicit end of bitstream checks
on the other loops

[...]
diff mbox

Patch

diff --git a/libavcodec/vp5.c b/libavcodec/vp5.c
index 54db620bde..b5f06a0940 100644
--- a/libavcodec/vp5.c
+++ b/libavcodec/vp5.c
@@ -38,8 +38,11 @@  static int vp5_parse_header(VP56Context *s, const uint8_t *buf, int buf_size)
 {
     VP56RangeCoder *c = &s->c;
     int rows, cols;
+    int ret;
 
-    ff_vp56_init_range_decoder(&s->c, buf, buf_size);
+    ret = ff_vp56_init_range_decoder(&s->c, buf, buf_size);
+    if (ret < 0)
+        return ret;
     s->frames[VP56_FRAME_CURRENT]->key_frame = !vp56_rac_get(c);
     vp56_rac_get(c);
     ff_vp56_init_dequant(s, vp56_rac_gets(c, 6));
diff --git a/libavcodec/vp56.h b/libavcodec/vp56.h
index e5c5bea963..c049399df8 100644
--- a/libavcodec/vp56.h
+++ b/libavcodec/vp56.h
@@ -224,7 +224,7 @@  int ff_vp56_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
  */
 
 extern const uint8_t ff_vp56_norm_shift[256];
-void ff_vp56_init_range_decoder(VP56RangeCoder *c, const uint8_t *buf, int buf_size);
+int ff_vp56_init_range_decoder(VP56RangeCoder *c, const uint8_t *buf, int buf_size);
 
 static av_always_inline unsigned int vp56_rac_renorm(VP56RangeCoder *c)
 {
diff --git a/libavcodec/vp56rac.c b/libavcodec/vp56rac.c
index 6061b7ee72..e70302bf85 100644
--- a/libavcodec/vp56rac.c
+++ b/libavcodec/vp56rac.c
@@ -37,11 +37,14 @@  const uint8_t ff_vp56_norm_shift[256]= {
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 };
 
-void ff_vp56_init_range_decoder(VP56RangeCoder *c, const uint8_t *buf, int buf_size)
+int ff_vp56_init_range_decoder(VP56RangeCoder *c, const uint8_t *buf, int buf_size)
 {
     c->high = 255;
     c->bits = -16;
     c->buffer = buf;
     c->end = buf + buf_size;
+    if (buf_size < 1)
+        return AVERROR_INVALIDDATA;
     c->code_word = bytestream_get_be24(&c->buffer);
+    return 0;
 }
diff --git a/libavcodec/vp6.c b/libavcodec/vp6.c
index 662126ca70..f0e60a3822 100644
--- a/libavcodec/vp6.c
+++ b/libavcodec/vp6.c
@@ -52,6 +52,7 @@  static int vp6_parse_header(VP56Context *s, const uint8_t *buf, int buf_size)
     int sub_version;
     int rows, cols;
     int res = 0;
+    int ret;
     int separated_coeff = buf[0] & 1;
 
     s->frames[VP56_FRAME_CURRENT]->key_frame = !(buf[0] & 0x80);
@@ -93,7 +94,7 @@  static int vp6_parse_header(VP56Context *s, const uint8_t *buf, int buf_size)
                 s->avctx->coded_width  = 16 * cols;
                 s->avctx->coded_height = 16 * rows;
             } else {
-                int ret = ff_set_dimensions(s->avctx, 16 * cols, 16 * rows);
+                ret = ff_set_dimensions(s->avctx, 16 * cols, 16 * rows);
                 if (ret < 0)
                     return ret;
 
@@ -105,7 +106,9 @@  static int vp6_parse_header(VP56Context *s, const uint8_t *buf, int buf_size)
             res = VP56_SIZE_CHANGE;
         }
 
-        ff_vp56_init_range_decoder(c, buf+6, buf_size-6);
+        ret = ff_vp56_init_range_decoder(c, buf+6, buf_size-6);
+        if (ret < 0)
+            return ret;
         vp56_rac_gets(c, 2);
 
         parse_filter_info = s->filter_header;
@@ -122,7 +125,9 @@  static int vp6_parse_header(VP56Context *s, const uint8_t *buf, int buf_size)
             buf += 2;
             buf_size -= 2;
         }
-        ff_vp56_init_range_decoder(c, buf+1, buf_size-1);
+        ret = ff_vp56_init_range_decoder(c, buf+1, buf_size-1);
+        if (ret < 0)
+            return ret;
 
         s->golden_frame = vp56_rac_get(c);
         if (s->filter_header) {
@@ -165,7 +170,9 @@  static int vp6_parse_header(VP56Context *s, const uint8_t *buf, int buf_size)
             s->parse_coeff = vp6_parse_coeff_huffman;
             init_get_bits(&s->gb, buf, buf_size<<3);
         } else {
-            ff_vp56_init_range_decoder(&s->cc, buf, buf_size);
+            ret = ff_vp56_init_range_decoder(&s->cc, buf, buf_size);
+            if (ret < 0)
+                return ret;
             s->ccp = &s->cc;
         }
     } else {
diff --git a/libavcodec/vp8.c b/libavcodec/vp8.c
index cc158528ef..8039e7817e 100644
--- a/libavcodec/vp8.c
+++ b/libavcodec/vp8.c
@@ -261,6 +261,7 @@  static int setup_partitions(VP8Context *s, const uint8_t *buf, int buf_size)
 {
     const uint8_t *sizes = buf;
     int i;
+    int ret;
 
     s->num_coeff_partitions = 1 << vp8_rac_get_uint(&s->c, 2);
 
@@ -274,13 +275,13 @@  static int setup_partitions(VP8Context *s, const uint8_t *buf, int buf_size)
         if (buf_size - size < 0)
             return -1;
 
-        ff_vp56_init_range_decoder(&s->coeff_partition[i], buf, size);
+        ret = ff_vp56_init_range_decoder(&s->coeff_partition[i], buf, size);
+        if (ret < 0)
+            return ret;
         buf      += size;
         buf_size -= size;
     }
-    ff_vp56_init_range_decoder(&s->coeff_partition[i], buf, buf_size);
-
-    return 0;
+    return ff_vp56_init_range_decoder(&s->coeff_partition[i], buf, buf_size);
 }
 
 static void vp7_get_quants(VP8Context *s)
@@ -518,7 +519,9 @@  static int vp7_decode_frame_header(VP8Context *s, const uint8_t *buf, int buf_si
 
     memcpy(s->put_pixels_tab, s->vp8dsp.put_vp8_epel_pixels_tab, sizeof(s->put_pixels_tab));
 
-    ff_vp56_init_range_decoder(c, buf, part1_size);
+    ret = ff_vp56_init_range_decoder(c, buf, part1_size);
+    if (ret < 0)
+        return ret;
     buf      += part1_size;
     buf_size -= part1_size;
 
@@ -570,7 +573,9 @@  static int vp7_decode_frame_header(VP8Context *s, const uint8_t *buf, int buf_si
     s->lf_delta.enabled        = 0;
 
     s->num_coeff_partitions = 1;
-    ff_vp56_init_range_decoder(&s->coeff_partition[0], buf, buf_size);
+    ret = ff_vp56_init_range_decoder(&s->coeff_partition[0], buf, buf_size);
+    if (ret < 0)
+        return ret;
 
     if (!s->macroblocks_base || /* first frame */
         width != s->avctx->width || height != s->avctx->height ||
@@ -699,7 +704,9 @@  static int vp8_decode_frame_header(VP8Context *s, const uint8_t *buf, int buf_si
         memset(&s->lf_delta, 0, sizeof(s->lf_delta));
     }
 
-    ff_vp56_init_range_decoder(c, buf, header_size);
+    ret = ff_vp56_init_range_decoder(c, buf, header_size);
+    if (ret < 0)
+        return ret;
     buf      += header_size;
     buf_size -= header_size;