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]

Reply via email to