diff mbox

[FFmpeg-devel,v2] avcodec/interplayvideo: Check sizes of decode buffers

Message ID 20170702214327.26804-1-hp@tmm.cx
State New
Headers show

Commit Message

Hein-Pieter van Braam July 2, 2017, 9:43 p.m. UTC
Fixes: 6503 crash with fuzzed file

Signed-off-by: Hein-Pieter van Braam <hp@tmm.cx>
---
 libavcodec/interplayvideo.c | 8 ++++++++
 1 file changed, 8 insertions(+)

Comments

Paul B Mahol July 3, 2017, 9:43 a.m. UTC | #1
On 7/2/17, Hein-Pieter van Braam <hp@tmm.cx> wrote:
> Fixes: 6503 crash with fuzzed file
>
> Signed-off-by: Hein-Pieter van Braam <hp@tmm.cx>
> ---
>  libavcodec/interplayvideo.c | 8 ++++++++
>  1 file changed, 8 insertions(+)
>
> diff --git a/libavcodec/interplayvideo.c b/libavcodec/interplayvideo.c
> index d6f484a..86530e6 100644
> --- a/libavcodec/interplayvideo.c
> +++ b/libavcodec/interplayvideo.c
> @@ -972,6 +972,8 @@ static void
> ipvideo_decode_format_06_opcodes(IpvideoContext *s, AVFrame *frame)
>                          x, y, opcode, bytestream2_tell(&s->stream_ptr));
>
>                  s->pixel_ptr = frame->data[0] + x + y * frame->linesize[0];
> +                if (s->pixel_ptr > (s->pixel_ptr +
> s->upper_motion_limit_offset))
> +                    return;

This looks strange.

>                  ipvideo_format_06_passes[pass](s, frame, opcode);
>              }
>          }
> @@ -1043,6 +1045,12 @@ static void
> ipvideo_decode_format_10_opcodes(IpvideoContext *s, AVFrame *frame)
>          for (y = 0; y < s->avctx->height; y += 8) {
>              for (x = 0; x < s->avctx->width; x += 8) {
>                  s->pixel_ptr = s->cur_decode_frame->data[0] + x + y *
> s->cur_decode_frame->linesize[0];
> +                if (s->pixel_ptr > s->pixel_ptr +
> s->upper_motion_limit_offset)
> +                    return;

This too.

> +
> +                if (s->cur_decode_frame->width != s->avctx->width ||
> +                        s->cur_decode_frame->height != s->avctx->height)
> +                    return;
>
>                  while (skip <= 0)  {
>                      if (skip != -0x8000 && skip) {
> --
> 2.9.4
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
Hein-Pieter van Braam July 3, 2017, 9:56 a.m. UTC | #2
On Mon, 2017-07-03 at 11:43 +0200, Paul B Mahol wrote:
> On 7/2/17, Hein-Pieter van Braam <hp@tmm.cx> wrote:
> > Fixes: 6503 crash with fuzzed file
> > 
> > Signed-off-by: Hein-Pieter van Braam <hp@tmm.cx>
> > ---
> >  libavcodec/interplayvideo.c | 8 ++++++++
> >  1 file changed, 8 insertions(+)
> > 
> > diff --git a/libavcodec/interplayvideo.c
> > b/libavcodec/interplayvideo.c
> > index d6f484a..86530e6 100644
> > --- a/libavcodec/interplayvideo.c
> > +++ b/libavcodec/interplayvideo.c
> > @@ -972,6 +972,8 @@ static void
> > ipvideo_decode_format_06_opcodes(IpvideoContext *s, AVFrame *frame)
> >                          x, y, opcode, bytestream2_tell(&s-
> > >stream_ptr));
> > 
> >                  s->pixel_ptr = frame->data[0] + x + y * frame-
> > >linesize[0];
> > +                if (s->pixel_ptr > (s->pixel_ptr +
> > s->upper_motion_limit_offset))
> > +                    return;
> 
> This looks strange.
> 

The code already has a feature to ensure that movement vectors can't
write past the end of the target AVFrame. I thought I'd reuse this to
prevent writing past the end of the current AVFrame for the 'regular'
pixeldata too. This code checks the value of the pointer into the
AVFrame's pixeldata is not further than the last 8x8 block so that we
can't write past it.

Would there be a better way of doing this?

Although, I suppose if I check the size of the AVFrame itself instead
then it would also be safe because of the for loop. I can also
implement it like that if that's preferred?

- HP
Paul B Mahol July 3, 2017, 9:59 a.m. UTC | #3
On 7/3/17, Hein-Pieter van Braam <hp@tmm.cx> wrote:
> On Mon, 2017-07-03 at 11:43 +0200, Paul B Mahol wrote:
>> On 7/2/17, Hein-Pieter van Braam <hp@tmm.cx> wrote:
>> > Fixes: 6503 crash with fuzzed file
>> >
>> > Signed-off-by: Hein-Pieter van Braam <hp@tmm.cx>
>> > ---
>> >  libavcodec/interplayvideo.c | 8 ++++++++
>> >  1 file changed, 8 insertions(+)
>> >
>> > diff --git a/libavcodec/interplayvideo.c
>> > b/libavcodec/interplayvideo.c
>> > index d6f484a..86530e6 100644
>> > --- a/libavcodec/interplayvideo.c
>> > +++ b/libavcodec/interplayvideo.c
>> > @@ -972,6 +972,8 @@ static void
>> > ipvideo_decode_format_06_opcodes(IpvideoContext *s, AVFrame *frame)
>> >                          x, y, opcode, bytestream2_tell(&s-
>> > >stream_ptr));
>> >
>> >                  s->pixel_ptr = frame->data[0] + x + y * frame-
>> > >linesize[0];
>> > +                if (s->pixel_ptr > (s->pixel_ptr +
>> > s->upper_motion_limit_offset))
>> > +                    return;
>>
>> This looks strange.
>>
>
> The code already has a feature to ensure that movement vectors can't
> write past the end of the target AVFrame. I thought I'd reuse this to
> prevent writing past the end of the current AVFrame for the 'regular'
> pixeldata too. This code checks the value of the pointer into the
> AVFrame's pixeldata is not further than the last 8x8 block so that we
> can't write past it.
>
> Would there be a better way of doing this?
>
> Although, I suppose if I check the size of the AVFrame itself instead
> then it would also be safe because of the for loop. I can also
> implement it like that if that's preferred?

You are comparing pointer with same pointer increased by some value.

This is wrong way to fix it.
Hein-Pieter van Braam July 3, 2017, 10:12 a.m. UTC | #4
On Mon, 2017-07-03 at 11:59 +0200, Paul B Mahol wrote:
> 
> 
> You are comparing pointer with same pointer increased by some value.
> 
> This is wrong way to fix it.

Urgh, you're right, of course. I don't know what I was thinking.
diff mbox

Patch

diff --git a/libavcodec/interplayvideo.c b/libavcodec/interplayvideo.c
index d6f484a..86530e6 100644
--- a/libavcodec/interplayvideo.c
+++ b/libavcodec/interplayvideo.c
@@ -972,6 +972,8 @@  static void ipvideo_decode_format_06_opcodes(IpvideoContext *s, AVFrame *frame)
                         x, y, opcode, bytestream2_tell(&s->stream_ptr));
 
                 s->pixel_ptr = frame->data[0] + x + y * frame->linesize[0];
+                if (s->pixel_ptr > (s->pixel_ptr + s->upper_motion_limit_offset))
+                    return;
                 ipvideo_format_06_passes[pass](s, frame, opcode);
             }
         }
@@ -1043,6 +1045,12 @@  static void ipvideo_decode_format_10_opcodes(IpvideoContext *s, AVFrame *frame)
         for (y = 0; y < s->avctx->height; y += 8) {
             for (x = 0; x < s->avctx->width; x += 8) {
                 s->pixel_ptr = s->cur_decode_frame->data[0] + x + y * s->cur_decode_frame->linesize[0];
+                if (s->pixel_ptr > s->pixel_ptr + s->upper_motion_limit_offset)
+                    return;
+
+                if (s->cur_decode_frame->width != s->avctx->width ||
+                        s->cur_decode_frame->height != s->avctx->height)
+                    return;
 
                 while (skip <= 0)  {
                     if (skip != -0x8000 && skip) {