[FFmpeg-devel] [PATCH] avcodec/cbs: use av_fast_realloc() in cbs_insert_unit()

James Almer jamrial at gmail.com
Sat Apr 11 17:01:41 EEST 2020


Fixes: Timeout
Fixes: 20791/clusterfuzz-testcase-minimized-ffmpeg_BSF_AV1_FRAME_SPLIT_fuzzer-5659537719951360
Fixes: 21214/clusterfuzz-testcase-minimized-ffmpeg_BSF_MPEG2_METADATA_fuzzer-5165560875974656
Fixes: 21247/clusterfuzz-testcase-minimized-ffmpeg_BSF_H264_METADATA_fuzzer-5715175257931776

Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
Signed-off-by: James Almer <jamrial at gmail.com>
---
This can be ported to av_fast_realloc_array() once that's committed.

 libavcodec/cbs.c | 37 ++++++++++++++++---------------------
 libavcodec/cbs.h |  7 +++++++
 2 files changed, 23 insertions(+), 21 deletions(-)

diff --git a/libavcodec/cbs.c b/libavcodec/cbs.c
index 0bd5e1ac5d..48ed7b5f32 100644
--- a/libavcodec/cbs.c
+++ b/libavcodec/cbs.c
@@ -161,6 +161,7 @@ void ff_cbs_fragment_free(CodedBitstreamContext *ctx,
 
     av_freep(&frag->units);
     frag->nb_units_allocated = 0;
+    frag->unit_buffer_size = 0;
 }
 
 static int cbs_read_fragment_content(CodedBitstreamContext *ctx,
@@ -684,35 +685,29 @@ static int cbs_insert_unit(CodedBitstreamContext *ctx,
                            CodedBitstreamFragment *frag,
                            int position)
 {
-    CodedBitstreamUnit *units;
+    CodedBitstreamUnit *units = frag->units;
 
-    if (frag->nb_units < frag->nb_units_allocated) {
-        units = frag->units;
+    if (frag->nb_units_allocated < frag->nb_units + 1) {
+        int new_size = frag->nb_units_allocated + 1;
+        void *tmp;
 
-        if (position < frag->nb_units)
-            memmove(units + position + 1, units + position,
-                    (frag->nb_units - position) * sizeof(*units));
-    } else {
-        units = av_malloc_array(frag->nb_units + 1, sizeof(*units));
-        if (!units)
+        if (new_size >= INT_MAX / sizeof(*units))
             return AVERROR(ENOMEM);
 
-        ++frag->nb_units_allocated;
-
-        if (position > 0)
-            memcpy(units, frag->units, position * sizeof(*units));
+        tmp = av_fast_realloc(units, &frag->unit_buffer_size,
+                              new_size * sizeof(*units));
+        if (!tmp)
+            return AVERROR(ENOMEM);
 
-        if (position < frag->nb_units)
-            memcpy(units + position + 1, frag->units + position,
-                   (frag->nb_units - position) * sizeof(*units));
+        frag->units = units = tmp;
+        frag->nb_units_allocated = new_size;
     }
 
-    memset(units + position, 0, sizeof(*units));
+    if (position < frag->nb_units)
+        memmove(units + position + 1, units + position,
+                (frag->nb_units - position) * sizeof(*units));
 
-    if (units != frag->units) {
-        av_free(frag->units);
-        frag->units = units;
-    }
+    memset(units + position, 0, sizeof(*units));
 
     ++frag->nb_units;
 
diff --git a/libavcodec/cbs.h b/libavcodec/cbs.h
index 9ca1fbd609..3209a82608 100644
--- a/libavcodec/cbs.h
+++ b/libavcodec/cbs.h
@@ -153,6 +153,13 @@ typedef struct CodedBitstreamFragment {
      */
      int             nb_units_allocated;
 
+    /**
+     * Size of allocated unit buffer.
+     *
+     * Must always be > nb_units_allocated; designed for internal use by cbs.
+     */
+     unsigned int    unit_buffer_size;
+
     /**
      * Pointer to an array of units of length nb_units_allocated.
      * Only the first nb_units are valid.
-- 
2.26.0



More information about the ffmpeg-devel mailing list