diff mbox series

[FFmpeg-devel,1/5] avcodec/avpacket: Improve overflow checks when packing dictionary

Message ID 20210317235958.1308987-1-andreas.rheinhardt@gmail.com
State Accepted
Commit 04d001ca9bc510be5bd1c75f6c8fe13751337799
Headers show
Series [FFmpeg-devel,1/5] avcodec/avpacket: Improve overflow checks when packing dictionary
Related show

Checks

Context Check Description
andriy/x86_make success Make finished
andriy/x86_make_fate success Make fate finished
andriy/PPC64_make success Make finished
andriy/PPC64_make_fate success Make fate finished

Commit Message

Andreas Rheinhardt March 17, 2021, 11:59 p.m. UTC
Also avoid reallocations.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
---
 libavcodec/avpacket.c | 40 ++++++++++++++++++++--------------------
 1 file changed, 20 insertions(+), 20 deletions(-)
diff mbox series

Patch

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)