From 206ff95fde1e00339e75fde608fb9f52f2fe8e64 Mon Sep 17 00:00:00 2001 From: Nicolas F Date: Sat, 13 Jun 2026 20:04:01 +0200 Subject: [PATCH 1/3] osdep/compiler: add MP_CKD_MUL Add a new MP_CKD_MUL macro which does a multiplication with overflow checking, backed by either the C23 ckd_mul standard function, or the GCC/Clang __builtin_mul_overflow otherwise. --- osdep/compiler.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osdep/compiler.h b/osdep/compiler.h index d3edecdb200c5..7639805f59337 100644 --- a/osdep/compiler.h +++ b/osdep/compiler.h @@ -7,6 +7,7 @@ #define MP_EXPAND_ARGS(...) __VA_ARGS__ #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L +#include #define MP_NORETURN [[noreturn]] #define MP_FALLTHROUGH [[fallthrough]] #define MP_WARN_UNUSED_RESULT [[nodiscard]] @@ -78,4 +79,10 @@ #define MP_SCANF_ATTRIBUTE(a1, a2) #endif +#if defined(__STDC_VERSION_STDCKDINT_H__) && __STDC_VERSION_STDCKDINT_H__ >= 202311L +#define MP_CKD_MUL(result, a, b) ckd_mul(result, a, b) +#elif __has_builtin(__builtin_mul_overflow) +#define MP_CKD_MUL(result, a, b) __builtin_mul_overflow(a, b, result) +#endif + #endif From 14b21966af9e34055a8c2365d28aef235f496982 Mon Sep 17 00:00:00 2001 From: Nicolas F Date: Sat, 13 Jun 2026 20:07:20 +0200 Subject: [PATCH 2/3] common/common: add saturating multiply macro Add a new function-like macro MP_SATURATE_MUL. It multiplies a * b and stores it in pointer "result", but sets "result" to its type's maximum value if it overflows. Evaluates to true if it saturated, otherwise false. --- common/common.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/common/common.h b/common/common.h index 5f56c60cdc154..27f0e92a65b83 100644 --- a/common/common.h +++ b/common/common.h @@ -22,6 +22,7 @@ #include #include #include +#include #include "config.h" @@ -65,6 +66,27 @@ // Return a+b, unless a is NOPTS. b must not be NOPTS. #define MP_ADD_PTS(a, b) ((a) == MP_NOPTS_VALUE ? (a) : ((a) + (b))) +// Return the maximum value representable by integer type of a. +#define MP_MAX_VAL(a) _Generic((a), \ + char: SCHAR_MAX, \ + unsigned char: UCHAR_MAX, \ + short: SHRT_MAX, \ + unsigned short: USHRT_MAX, \ + int: INT_MAX, \ + unsigned int: UINT_MAX, \ + long: LONG_MAX, \ + unsigned long: ULONG_MAX, \ + long long: LLONG_MAX, \ + unsigned long long: ULLONG_MAX) + +// Multiply a * b and store in result. If result would overflow, saturate at +// its maximum value instead, and return true. Otherwise, return false. +#define MP_SATURATE_MUL(result, a, b) ( \ + MP_CKD_MUL(result, a, b) ? \ + *result = MP_MAX_VAL(*result), true : \ + false \ +) + #define CONTROL_OK 1 #define CONTROL_TRUE 1 #define CONTROL_FALSE 0 From 7e7934c4a4dfa4884e5e26c91982fc9cea1ea3f8 Mon Sep 17 00:00:00 2001 From: Nicolas F Date: Sat, 13 Jun 2026 20:10:02 +0200 Subject: [PATCH 3/3] demux_edl: fix signed integer overflow in HLS bitrate Use the new MP_SATURATE_MUL to prevent hls_bitrate from overflowing when being multiplied by 8. Fixes: #18120 --- demux/demux_edl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demux/demux_edl.c b/demux/demux_edl.c index 8e043e6983ad5..71351b8b15323 100644 --- a/demux/demux_edl.c +++ b/demux/demux_edl.c @@ -243,7 +243,7 @@ static struct tl_root *parse_edl(bstr str, struct mp_log *log) : get_meta(tl, index); sh->lang = get_param0(&ctx, sh, "lang"); sh->title = get_param0(&ctx, sh, "title"); - sh->hls_bitrate = get_param_int(&ctx, "byterate", 0) * 8; + MP_SATURATE_MUL(&sh->hls_bitrate, get_param_int(&ctx, "byterate", 0), 8); int pid = get_param_int(&ctx, "program_id", -1); if (pid >= 0) MP_TARRAY_APPEND(sh, sh->program_ids, sh->num_program_ids, pid);