PR #23513 opened by tguilbert-google URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23513 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23513.patch
In `discard_samples()`, the rescaling operation can evaluate to AV_NOPTS_VALUE if the rescaling operation overflows. This commit prevents adjusting timestamp and durations by the invalid value. # Summary of changes - Explicitly checking if diff_ts is AV_NOPTS_VALUE. If so, invalidate the frame's pts/dts and reset its duration to 0 (unknown). - Using saturating arithmetic (av_sat_add64 and av_sat_sub64) when adjusting valid timestamps. - Ensuring duration is set to 0 instead of AV_NOPTS_VALUE if rescaling fails in the discard padding path. Attached is a fuzzer generated file which causes undefined behavior (integer overflow) in Chromium. However, the file does not crash when directly opened in FFmpeg (built with UBSAN), since the parsing exits early due to other errors. <!-- If this PR requires new FATE test samples, attach them to the PR and list their target paths below (relative to the fate-suite root). Attached filenames must match the sample's filename: ```fate-samples # e.g. vorbis/new-sample.ogg ``` --> >From a717e81a4821330360bb1eab96818d468522ab72 Mon Sep 17 00:00:00 2001 From: Thomas Guilbert <[email protected]> Date: Wed, 17 Jun 2026 03:18:51 +0000 Subject: [PATCH] Guard against int overflow when discarding samples In `discard_samples()`, the rescaling operation can evaluate to AV_NOPTS_VALUE if the rescaling operation overflows. This commit prevents adjusting timestamp and durations by the invalid value. --- libavcodec/decode.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index c82e357845..e47e506816 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -371,12 +371,18 @@ static int discard_samples(AVCodecContext *avctx, AVFrame *frame, int64_t *disca int64_t diff_ts = av_rescale_q(avci->skip_samples, (AVRational){1, avctx->sample_rate}, avctx->pkt_timebase); - if (frame->pts != AV_NOPTS_VALUE) - frame->pts += diff_ts; - if (frame->pkt_dts != AV_NOPTS_VALUE) - frame->pkt_dts += diff_ts; - if (frame->duration >= diff_ts) - frame->duration -= diff_ts; + if (diff_ts != AV_NOPTS_VALUE) { + if (frame->pts != AV_NOPTS_VALUE) + frame->pts = av_sat_add64(frame->pts, diff_ts); + if (frame->pkt_dts != AV_NOPTS_VALUE) + frame->pkt_dts = av_sat_add64(frame->pkt_dts, diff_ts); + if (frame->duration >= diff_ts) + frame->duration = av_sat_sub64(frame->duration, diff_ts); + } else { + frame->pts = AV_NOPTS_VALUE; + frame->pkt_dts = AV_NOPTS_VALUE; + frame->duration = 0; + } } else av_log(avctx, AV_LOG_WARNING, "Could not update timestamps for skipped samples.\n"); @@ -397,7 +403,7 @@ static int discard_samples(AVCodecContext *avctx, AVFrame *frame, int64_t *disca int64_t diff_ts = av_rescale_q(frame->nb_samples - discard_padding, (AVRational){1, avctx->sample_rate}, avctx->pkt_timebase); - frame->duration = diff_ts; + frame->duration = diff_ts == AV_NOPTS_VALUE ? 0 : diff_ts; } else av_log(avctx, AV_LOG_WARNING, "Could not update timestamps for discarded samples.\n"); -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
