avcodec/utils: Clear dimensions in ff_get_buffer() on failure
authorMichael Niedermayer <michael@niedermayer.cc>
Sat, 28 Nov 2015 18:08:46 +0000 (19:08 +0100)
committerMike Gabriel <sunweaver@debian.org>
Tue, 28 May 2019 12:14:01 +0000 (13:14 +0100)
avcodec/utils: Clear dimensions in ff_get_buffer() on failure

Fixes out of array access
Fixes: 482d8f2fd17c9f532b586458a33f267c/asan_heap-oob_4a52b6_7417_1d08d477736d66cdadd833d146bb8bae.mov
Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
[sunweaver] - manually adapted for Debian jessie's libav version which lacks the get_internal_buffer() symbol.

Gbp-Pq: Name CVE-2015-8663.patch

libavcodec/utils.c

index c5fa50d06b8502b508e9f4f75ec5db01ace0e63f..ba29f6352ab91da68ae68a8cf4783ca17e76a876 100644 (file)
@@ -617,6 +617,10 @@ int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
 
     switch (avctx->codec_type) {
     case AVMEDIA_TYPE_VIDEO:
+        if (av_image_check_size(avctx->width, avctx->height, 0, avctx) < 0) {
+            frame->width = frame->height = 0;
+            return AVERROR(EINVAL);
+        }
         if (frame->width <= 0 || frame->height <= 0) {
             frame->width  = FFMAX(avctx->width, avctx->coded_width);
             frame->height = FFMAX(avctx->height, avctx->coded_height);
@@ -634,9 +638,6 @@ int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
                    frame->sample_aspect_ratio.den);
             frame->sample_aspect_ratio = (AVRational){ 0, 1 };
         }
-
-        if ((ret = av_image_check_size(avctx->width, avctx->height, 0, avctx)) < 0)
-            return ret;
         break;
     case AVMEDIA_TYPE_AUDIO:
         if (!frame->sample_rate)
@@ -670,8 +671,11 @@ int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
     }
 
     ret = ff_decode_frame_props(avctx, frame);
-    if (ret < 0)
+    if (ret < 0) {
+        if (avctx->codec_type == AVMEDIA_TYPE_VIDEO)
+            frame->width = frame->height = 0;
         return ret;
+    }
 
     if (hwaccel && hwaccel->alloc_frame) {
         ret = hwaccel->alloc_frame(avctx, frame);
@@ -696,8 +700,11 @@ FF_DISABLE_DEPRECATION_WARNINGS
             frame->reference    = 1;
 
         ret = avctx->get_buffer(avctx, frame);
-        if (ret < 0)
+        if (ret < 0) {
+            if (avctx->codec_type == AVMEDIA_TYPE_VIDEO)
+                frame->width = frame->height = 0;
             return ret;
+        }
 
         /* return if the buffers are already set up
          * this would happen e.g. when a custom get_buffer() calls
@@ -789,6 +796,8 @@ fail:
         avctx->release_buffer(avctx, frame);
         av_freep(&priv);
         av_buffer_unref(&dummy_buf);
+        if (avctx->codec_type ==  AVMEDIA_TYPE_VIDEO)
+            frame->width = frame->height = 0;
         return ret;
     }
 FF_ENABLE_DEPRECATION_WARNINGS
@@ -802,6 +811,9 @@ end:
         frame->height = avctx->height;
     }
 
+    if ((ret < 0) && (avctx->codec_type ==  AVMEDIA_TYPE_VIDEO))
+        frame->width = frame->height = 0;
+
     return ret;
 }