[FFmpeg-cvslog] avcodec/avpacket: Improve overflow checks when packing dictionary

Andreas Rheinhardt git at videolan.org
Fri Mar 19 05:31:38 EET 2021


ffmpeg | branch: master | Andreas Rheinhardt <andreas.rheinhardt at gmail.com> | Wed Mar 17 18:32:36 2021 +0100| [04d001ca9bc510be5bd1c75f6c8fe13751337799] | committer: Andreas Rheinhardt

avcodec/avpacket: Improve overflow checks when packing dictionary

Also avoid reallocations.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt at gmail.com>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=04d001ca9bc510be5bd1c75f6c8fe13751337799
---

 libavcodec/avpacket.c | 40 ++++++++++++++++++++--------------------
 1 file changed, 20 insertions(+), 20 deletions(-)

diff --git a/libavcodec/avpacket.c b/libavcodec/avpacket.c
index 6840688b15..8f0850fb00 100644
--- a/libavcodec/avpacket.c
+++ b/libavcodec/avpacket.c
@@ -509,37 +509,37 @@ int av_packet_split_side_data(AVPacket *pkt){
 
 uint8_t *av_packet_pack_dictionary(AVDictionary *dict, int *size)
 {
-    AVDictionaryEntry *t = NULL;
     uint8_t *data = NULL;
     *size = 0;
 
     if (!dict)
         return NULL;
 
-    while ((t = av_dict_get(dict, "", t, AV_DICT_IGNORE_SUFFIX))) {
-        const size_t keylen   = strlen(t->key);
-        const size_t valuelen = strlen(t->value);
-        const size_t new_size = *size + keylen + 1 + valuelen + 1;
-        uint8_t *const new_data = av_realloc(data, new_size);
+    for (int pass = 0; pass < 2; pass++) {
+        const AVDictionaryEntry *t = NULL;
+        size_t total_length = 0;
 
-        if (!new_data)
-            goto fail;
-        data = new_data;
-        if (new_size > INT_MAX)
-            goto fail;
-
-        memcpy(data + *size, t->key, keylen + 1);
-        memcpy(data + *size + keylen + 1, t->value, valuelen + 1);
+        while ((t = av_dict_get(dict, "", t, AV_DICT_IGNORE_SUFFIX))) {
+            for (int i = 0; i < 2; i++) {
+                const char  *str = i ? t->value : t->key;
+                const size_t len = strlen(str) + 1;
 
-        *size = new_size;
+                if (pass)
+                    memcpy(data + total_length, str, len);
+                else if (len > INT_MAX - total_length)
+                    return NULL;
+                total_length += len;
+            }
+        }
+        if (pass)
+            break;
+        data = av_malloc(total_length);
+        if (!data)
+            return NULL;
+        *size = total_length;
     }
 
     return data;
-
-fail:
-    av_freep(&data);
-    *size = 0;
-    return NULL;
 }
 
 int av_packet_unpack_dictionary(const uint8_t *data, int size, AVDictionary **dict)



More information about the ffmpeg-cvslog mailing list