[FFmpeg-devel] [PATCH 3/4] dict.c: Free non-strduped av_dict_set arguments on error.

wm4 nfxjfg at googlemail.com
Mon Aug 11 22:11:59 CEST 2014


On Mon, 11 Aug 2014 21:17:18 +0200
Reimar Döffinger <Reimar.Doeffinger at gmx.de> wrote:

> Unfortunately this was not explicitly documented and thus
> might be very risky.
> But basically all uses I saw in FFmpeg had a memleak in these
> cases.

It's the more convenient behavior, although on the other hand it feels
wrong to change the input data on error.

This makes me wonder, isn't AV_DICT_DONT_STRDUP_* too obscure and too
much of a microoptimization, that we have to risk retro-guessing these
subtle semantics?

(But the patch is probably OK, IMHO.)

> 
> Signed-off-by: Reimar Döffinger <Reimar.Doeffinger at gmx.de>
> ---
>  libavutil/dict.c | 9 +++++++--
>  libavutil/dict.h | 2 ++
>  2 files changed, 9 insertions(+), 2 deletions(-)
> 
> diff --git a/libavutil/dict.c b/libavutil/dict.c
> index 9fdc6d6..f23b768 100644
> --- a/libavutil/dict.c
> +++ b/libavutil/dict.c
> @@ -91,7 +91,7 @@ int av_dict_set(AVDictionary **pm, const char *key, const char *value,
>          AVDictionaryEntry *tmp = av_realloc(m->elems,
>                                              (m->count + 1) * sizeof(*m->elems));
>          if (!tmp)
> -            return AVERROR(ENOMEM);
> +            goto err_out;
>          m->elems = tmp;
>      }
>      if (value) {
> @@ -105,7 +105,7 @@ int av_dict_set(AVDictionary **pm, const char *key, const char *value,
>              int len = strlen(oldval) + strlen(value) + 1;
>              char *newval = av_mallocz(len);
>              if (!newval)
> -                return AVERROR(ENOMEM);
> +                goto err_out;
>              av_strlcat(newval, oldval, len);
>              av_freep(&oldval);
>              av_strlcat(newval, value, len);
> @@ -120,6 +120,11 @@ int av_dict_set(AVDictionary **pm, const char *key, const char *value,
>      }
>  
>      return 0;
> +
> +err_out:
> +    if (flags & AV_DICT_DONT_STRDUP_KEY) av_free(key);
> +    if (flags & AV_DICT_DONT_STRDUP_VAL) av_free(value);
> +    return AVERROR(ENOMEM);
>  }
>  
>  int av_dict_set_int(AVDictionary **pm, const char *key, int64_t value,
> diff --git a/libavutil/dict.h b/libavutil/dict.h
> index 06f1621..5e319fe 100644
> --- a/libavutil/dict.h
> +++ b/libavutil/dict.h
> @@ -115,6 +115,8 @@ int av_dict_count(const AVDictionary *m);
>  /**
>   * Set the given entry in *pm, overwriting an existing entry.
>   *
> + * Note: On error non-av_strduped arguments will be freed.
> + *

That doesn't really explain anything. Suggestion: mention
AV_DICT_DONT_STRDUP_* explicitly, and mention that the corresponding
argument will always be freed, even on error.

>   * @param pm pointer to a pointer to a dictionary struct. If *pm is NULL
>   * a dictionary struct is allocated and put in *pm.
>   * @param key entry key to add to *pm (will be av_strduped depending on flags)



More information about the ffmpeg-devel mailing list