From a8c5b4551e03085bb8973c7b3c5d0ef55d24de0c Mon Sep 17 00:00:00 2001 From: Lukasz Marek Date: Wed, 1 Apr 2015 20:01:30 +0200 Subject: [PATCH] lavu/dict: fix set function when reuse existing key pointer Fixes following scenario: av_dict_set(&d, "key", "old", 0); AVDictionaryEentry *e = av_dict_get(d, "key", NULL, 0); av_dict_set(&d, e->key, "new", 0); Signed-off-by: Lukasz Marek --- libavutil/dict.c | 44 ++++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/libavutil/dict.c b/libavutil/dict.c index 85613da19e..e30988dd9c 100644 --- a/libavutil/dict.c +++ b/libavutil/dict.c @@ -71,17 +71,25 @@ int av_dict_set(AVDictionary **pm, const char *key, const char *value, { AVDictionary *m = *pm; AVDictionaryEntry *tag = av_dict_get(m, key, NULL, flags); - char *oldval = NULL; + char *oldval = NULL, *copy_key = NULL, *copy_value = NULL; + if (flags & AV_DICT_DONT_STRDUP_KEY) + copy_key = (void *)key; + else + copy_key = av_strdup(key); + if (flags & AV_DICT_DONT_STRDUP_VAL) + copy_value = (void *)value; + else if (copy_key) + copy_value = av_strdup(value); if (!m) m = *pm = av_mallocz(sizeof(*m)); - if (!m) + if (!m || (key && !copy_key) || (value && !copy_value)) goto err_out; if (tag) { if (flags & AV_DICT_DONT_OVERWRITE) { - if (flags & AV_DICT_DONT_STRDUP_KEY) av_free((void*)key); - if (flags & AV_DICT_DONT_STRDUP_VAL) av_free((void*)value); + av_free(copy_key); + av_free(copy_value); return 0; } if (flags & AV_DICT_APPEND) @@ -97,27 +105,23 @@ int av_dict_set(AVDictionary **pm, const char *key, const char *value, goto err_out; m->elems = tmp; } - if (value) { - if (flags & AV_DICT_DONT_STRDUP_KEY) - m->elems[m->count].key = (char*)(intptr_t)key; - else - m->elems[m->count].key = av_strdup(key); - if (!m->elems[m->count].key) - goto err_out; - if (flags & AV_DICT_DONT_STRDUP_VAL) { - m->elems[m->count].value = (char*)(intptr_t)value; - } else if (oldval && flags & AV_DICT_APPEND) { - int len = strlen(oldval) + strlen(value) + 1; + if (copy_value) { + m->elems[m->count].key = copy_key; + m->elems[m->count].value = copy_value; + if (oldval && flags & AV_DICT_APPEND) { + int len = strlen(oldval) + strlen(copy_value) + 1; char *newval = av_mallocz(len); if (!newval) goto err_out; av_strlcat(newval, oldval, len); av_freep(&oldval); - av_strlcat(newval, value, len); + av_strlcat(newval, copy_value, len); m->elems[m->count].value = newval; - } else - m->elems[m->count].value = av_strdup(value); + av_freep(©_value); + } m->count++; + } else { + av_freep(©_key); } if (!m->count) { av_freep(&m->elems); @@ -131,8 +135,8 @@ err_out: av_freep(&m->elems); av_freep(pm); } - if (flags & AV_DICT_DONT_STRDUP_KEY) av_free((void*)key); - if (flags & AV_DICT_DONT_STRDUP_VAL) av_free((void*)value); + av_free(copy_key); + av_free(copy_value); return AVERROR(ENOMEM); }