summaryrefslogtreecommitdiff
path: root/libavutil
diff options
context:
space:
mode:
authorAndreas Rheinhardt <andreas.rheinhardt@outlook.com>2022-09-13 21:07:19 +0200
committerAndreas Rheinhardt <andreas.rheinhardt@outlook.com>2022-09-14 19:01:02 +0200
commite867a29ec1eb71a5841e452a4f2bf946c096282a (patch)
treefc7427ab607e47b124941e70d2a81d0d44cd25b6 /libavutil
parentc15dd31d2a9067b3aa7a575f585f44d62e9d5454 (diff)
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@gmail.com> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Diffstat (limited to 'libavutil')
-rw-r--r--libavutil/dict.c13
1 files 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) {