]> git.sesse.net Git - ffmpeg/commitdiff
avcodec/avpacket: Improve overflow checks when packing dictionary
authorAndreas Rheinhardt <andreas.rheinhardt@gmail.com>
Wed, 17 Mar 2021 17:32:36 +0000 (18:32 +0100)
committerAndreas Rheinhardt <andreas.rheinhardt@gmail.com>
Fri, 19 Mar 2021 02:03:06 +0000 (03:03 +0100)
Also avoid reallocations.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
libavcodec/avpacket.c

index 6840688b15eab00c46449c515f307c35f225bc46..8f0850fb00952a8400eee32100bd74f3544e8c52 100644 (file)
@@ -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)