[FFmpeg-cvslog] avutil/dict: Improve appending values

Andreas Rheinhardt git at videolan.org
Wed Sep 14 20:07:29 EEST 2022


ffmpeg | branch: master | Andreas Rheinhardt <andreas.rheinhardt at outlook.com> | Tue Sep 13 21:07:19 2022 +0200| [e867a29ec1eb71a5841e452a4f2bf946c096282a] | committer: Andreas Rheinhardt

avutil/dict: Improve appending values

When appending two values (due to AV_DICT_APPEND), the earlier code
would first zero-allocate a buffer of the required size and then
copy both parts into it via av_strlcat(). This is problematic,
as it leads to quadratic performance in case of frequent enlargements.
Fix this by using av_realloc() (which is hopefully designed to handle
such cases in a better way than simply throwing the buffer we already
have away) and by copying the string via memcpy() (after all, we already
calculated the strlen of both strings).

Reviewed-by: Paul B Mahol <onemda at gmail.com>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt at outlook.com>

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

 libavutil/dict.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/libavutil/dict.c b/libavutil/dict.c
index aa64fb990c..4bba041d0a 100644
--- a/libavutil/dict.c
+++ b/libavutil/dict.c
@@ -98,16 +98,17 @@ int av_dict_set(AVDictionary **pm, const char *key, const char *value,
             return 0;
         }
         if (copy_value && flags & AV_DICT_APPEND) {
-            size_t len = strlen(tag->value) + strlen(copy_value) + 1;
-            char *newval = av_mallocz(len);
+            size_t oldlen = strlen(tag->value);
+            size_t new_part_len = strlen(copy_value);
+            size_t len = oldlen + new_part_len + 1;
+            char *newval = av_realloc(tag->value, len);
             if (!newval)
                 goto err_out;
-            av_strlcat(newval, tag->value, len);
-            av_strlcat(newval, copy_value, len);
+            memcpy(newval + oldlen, copy_value, new_part_len + 1);
             av_freep(&copy_value);
             copy_value = newval;
-        }
-        av_free(tag->value);
+        } else
+            av_free(tag->value);
         av_free(tag->key);
         *tag = m->elems[--m->count];
     } else if (copy_value) {



More information about the ffmpeg-cvslog mailing list