[FFmpeg-cvslog] avutil/opt: Don't cast when the result might be misaligned

Andreas Rheinhardt git at videolan.org
Thu Mar 28 05:01:56 EET 2024


ffmpeg | branch: master | Andreas Rheinhardt <andreas.rheinhardt at outlook.com> | Mon Mar 25 14:54:35 2024 +0100| [c85477f78d7916b663bd09169c7ce8d4d345bca3] | committer: Andreas Rheinhardt

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 at outlook.com>

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

 libavutil/opt.c | 29 +++++++++++++++--------------
 1 file 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);



More information about the ffmpeg-cvslog mailing list