diff options
author | Andreas Rheinhardt <andreas.rheinhardt@outlook.com> | 2024-03-25 14:54:35 +0100 |
---|---|---|
committer | Andreas Rheinhardt <andreas.rheinhardt@outlook.com> | 2024-03-28 03:08:01 +0100 |
commit | c85477f78d7916b663bd09169c7ce8d4d345bca3 (patch) | |
tree | 36323588d9dcde460a174d8710b342a88df3836e | |
parent | aa7d6520e6335f9ed45ca2bf0fbf932fb4b2dea6 (diff) | |
download | ffmpeg-c85477f78d7916b663bd09169c7ce8d4d345bca3.tar.gz |
avutil/opt: Don't cast when the result might be misaligned
A pointer conversion is UB if the resulting pointer is not
correctly aligned for the resultant type, even if no
load/store is ever performed through that pointer (C11 6.3.2.3 (7)).
This may happen in opt_copy_elem(), because the pointers are
converted even when they belong to a type that does not guarantee
sufficient alignment.
Fix this by deferring the cast after having checked the type.
Also make the casts -Wcast-qual safe and avoid an indirection
for src.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
-rw-r--r-- | libavutil/opt.c | 29 |
1 files changed, 15 insertions, 14 deletions
diff --git a/libavutil/opt.c b/libavutil/opt.c index 00e11d1341..5feb5b2cb7 100644 --- a/libavutil/opt.c +++ b/libavutil/opt.c @@ -2028,18 +2028,19 @@ void *av_opt_ptr(const AVClass *class, void *obj, const char *name) static int opt_copy_elem(void *logctx, enum AVOptionType type, void *dst, const void *src) { - uint8_t **dst8 = (uint8_t **)dst; - const uint8_t **src8 = (const uint8_t **)src; - if (type == AV_OPT_TYPE_STRING) { - if (*dst8 != *src8) - av_freep(dst8); - if (*src8) { - *dst8 = av_strdup(*src8); - if (!*dst8) + const char *src_str = *(const char *const *)src; + char **dstp = (char **)dst; + if (*dstp != src_str) + av_freep(dstp); + if (src_str) { + *dstp = av_strdup(src_str); + if (!*dstp) return AVERROR(ENOMEM); } } else if (type == AV_OPT_TYPE_BINARY) { + const uint8_t *const *src8 = (const uint8_t *const *)src; + uint8_t **dst8 = (uint8_t **)dst; int len = *(const int *)(src8 + 1); if (*dst8 != *src8) av_freep(dst8); @@ -2052,12 +2053,12 @@ static int opt_copy_elem(void *logctx, enum AVOptionType type, } else if (type == AV_OPT_TYPE_CONST) { // do nothing } else if (type == AV_OPT_TYPE_DICT) { - AVDictionary **sdict = (AVDictionary **)src; - AVDictionary **ddict = (AVDictionary **)dst; - if (*sdict != *ddict) - av_dict_free(ddict); - *ddict = NULL; - return av_dict_copy(ddict, *sdict, 0); + const AVDictionary *sdict = *(const AVDictionary * const *)src; + AVDictionary **ddictp = (AVDictionary **)dst; + if (sdict != *ddictp) + av_dict_free(ddictp); + *ddictp = NULL; + return av_dict_copy(ddictp, sdict, 0); } else if (type == AV_OPT_TYPE_CHLAYOUT) { if (dst != src) return av_channel_layout_copy(dst, src); |