PR #23409 opened by iceray URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23409 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23409.patch
# Summary of changes This PR fixes **two** UBSan-reported undefined behavior issues found by fuzzing with the upstream demuxer fuzz target. ### `libavcodec/cbs_av1.c`: The AV1 coded bitstream assembler concatenates each unit's bitstream data into `frag->data`. A fuzzed AV1 input can produce a unit with `data == NULL` and `data_size == 0`. Calling `memcpy(dst, NULL, 0)` is still undefined behavior under the C library `nonnull` contract, and UBSan reports it as: ```text libavcodec/cbs_av1.c:1256:34: runtime error: null pointer passed as argument 2, which is declared to never be null ``` The fix validates that positive-sized units have a data pointer before assembling the fragment, and skips `memcpy()` for zero-sized units. ### `libavformat/sbgdec.c`: The SBG demuxer parses the `-F` fade time option with `strtod()` and then stores the converted timestamp in an `int64_t` field. Extremely large values can exceed the representable range of the destination integer type, which UBSan reports as: ```text libavformat/sbgdec.c:386:44: runtime error: 1.84467e+22 is outside the range of representable values of type 'long' ``` The fix rejects negative, NaN, infinite, and out-of-range `-F` values before the double-to-integer conversion, using the existing `syntax error for option -F` error path. Both fixes are narrowly scoped to the affected functions and make malformed fuzzer inputs fail parsing/assembly cleanly instead of reaching undefined behavior. No new FATE samples are included. # Local validation Validated against FFmpeg 8.1 origin build with `tools/target_dem_fuzzer`. For `libavcodec/cbs_av1.c`: ```text origin replay exit: 134 origin UBSan: libavcodec/cbs_av1.c:1256:34: null pointer passed as argument 2 fixed replay exit: 0 ``` For `libavformat/sbgdec.c`: ```text origin replay exit: 134 origin UBSan: libavformat/sbgdec.c:386:44: value outside representable range of type 'long' fixed replay exit: 0 ``` >From 85bbc84ff6ff3612d47df329972ceebd2996ef76 Mon Sep 17 00:00:00 2001 From: iceray <[email protected]> Date: Mon, 8 Jun 2026 13:02:26 +0000 Subject: [PATCH 1/2] Update to fix UBSan Bug by iceray origin: `runtime error: null pointer passed as argument 2, which is declared to never be null` --- libavcodec/cbs_av1.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/libavcodec/cbs_av1.c b/libavcodec/cbs_av1.c index deb73c8ebb..c60bee4225 100644 --- a/libavcodec/cbs_av1.c +++ b/libavcodec/cbs_av1.c @@ -1242,8 +1242,11 @@ static int cbs_av1_assemble_fragment(CodedBitstreamContext *ctx, int i; size = 0; - for (i = 0; i < frag->nb_units; i++) + for (i = 0; i < frag->nb_units; i++) { + if (frag->units[i].data_size && !frag->units[i].data) + return AVERROR_INVALIDDATA; size += frag->units[i].data_size; + } frag->data_ref = av_buffer_alloc(size + AV_INPUT_BUFFER_PADDING_SIZE); if (!frag->data_ref) @@ -1253,8 +1256,9 @@ static int cbs_av1_assemble_fragment(CodedBitstreamContext *ctx, pos = 0; for (i = 0; i < frag->nb_units; i++) { - memcpy(frag->data + pos, frag->units[i].data, - frag->units[i].data_size); + if (frag->units[i].data_size) + memcpy(frag->data + pos, frag->units[i].data, + frag->units[i].data_size); pos += frag->units[i].data_size; } av_assert0(pos == size); -- 2.52.0 >From c2e701a14770f8dbd69ce17d2766e4a8eb32f57d Mon Sep 17 00:00:00 2001 From: iceray <[email protected]> Date: Mon, 8 Jun 2026 13:06:16 +0000 Subject: [PATCH 2/2] Update to fix UBSan Bug by iceray in libavformat/sbgdec.c:386:44 runtime error: 1.84467e+22 is outside the range of representable values of type 'long' --- libavformat/sbgdec.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libavformat/sbgdec.c b/libavformat/sbgdec.c index 71cbad2dae..e1f202ffea 100644 --- a/libavformat/sbgdec.c +++ b/libavformat/sbgdec.c @@ -384,6 +384,11 @@ static int parse_options(struct sbg_parser *p) "syntax error for option -F"); return AVERROR_INVALIDDATA; } + if (!(v >= 0 && v <= (double)(INT64_MAX / (AV_TIME_BASE / 1000)))) { + snprintf(p->err_msg, sizeof(p->err_msg), + "syntax error for option -F"); + return AVERROR_INVALIDDATA; + } p->scs.opt_fade_time = v * AV_TIME_BASE / 1000; break; case 'L': -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
