PR #25694 opened by michaelni
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25694
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25694.patch


>From 900ccad16d2f86975094f27d2d99b78ea83fc228 Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Fri, 30 Oct 2026 19:31:36 +0100
Subject: [PATCH 1/7] avcodec/pcm-dvdenc: do not encode a frame with fewer
 samples than a block

24 bit samples are stored in blocks of samples_per_block samples
and the sample count of a frame is rounded down to whole blocks. A last
frame with fewer samples than a block gives zero blocks, the do/while
loops still run and read past the frame until the block count wraps.

Return no packet for such a frame.

Fixes: out of array read
Fixes: ZplUzGvg2XP9
Fixes: AISLE-2026-0150-00112
Out of array read Replicated through UnModified FFmpeg with ASAN

Found-by: Joshua Rogers (AISLE)
---
 libavcodec/pcm-dvdenc.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/libavcodec/pcm-dvdenc.c b/libavcodec/pcm-dvdenc.c
index 4904eea4ca5..dc5224cc24c 100644
--- a/libavcodec/pcm-dvdenc.c
+++ b/libavcodec/pcm-dvdenc.c
@@ -123,6 +123,9 @@ static int pcm_dvd_encode_frame(AVCodecContext *avctx, 
AVPacket *avpkt,
     PutByteContext pb;
     int ret;
 
+    if (!blocks)
+        return 0;
+
     if ((ret = ff_get_encode_buffer(avctx, avpkt, pkt_size, 0)) < 0)
         return ret;
 
-- 
2.54.0


>From a4530271fdee4e9bc065088f862e3d6174adabd4 Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Mon, 2 Nov 2026 18:49:47 +0100
Subject: [PATCH 2/7] avcodec/ttaenc: check the packet space for each sample
 and the CRC

Fixes: Assertion failure
Fixes: bAfKKmQm4ZDe
Fixes: AISLE-2026-0150-00078
Assertion failure Replicated through UnModified FFmpeg

Found-by: Joshua Rogers (AISLE)
---
 libavcodec/ttaenc.c | 37 +++++++++++++++++++------------------
 1 file changed, 19 insertions(+), 18 deletions(-)

diff --git a/libavcodec/ttaenc.c b/libavcodec/ttaenc.c
index 46751ff3ca6..24f85cade88 100644
--- a/libavcodec/ttaenc.c
+++ b/libavcodec/ttaenc.c
@@ -90,7 +90,7 @@ static int tta_encode_frame(AVCodecContext *avctx, AVPacket 
*avpkt,
     TTAEncContext *s = avctx->priv_data;
     PutBitContext pb;
     int ret, i, out_bytes, cur_chan, res, samples;
-    int64_t pkt_size =  frame->nb_samples * 2LL * avctx->ch_layout.nb_channels 
* s->bps;
+    int64_t pkt_size =  frame->nb_samples * 2LL * avctx->ch_layout.nb_channels 
* s->bps + 4;
 
 pkt_alloc:
     cur_chan = 0, res = 0, samples = 0;
@@ -109,7 +109,7 @@ pkt_alloc:
         TTAChannel *c = &s->ch_ctx[cur_chan];
         TTAFilter *filter = &c->filter;
         TTARice *rice = &c->rice;
-        uint32_t k, unary, outval;
+        uint32_t k, unary = 0, outval;
         int32_t value, temp;
 
         value = get_sample(frame, samples++, avctx->sample_fmt);
@@ -153,23 +153,24 @@ pkt_alloc:
                 rice->k1++;
 
             unary = 1 + (outval >> k);
-            if (unary + 100LL > put_bits_left(&pb)) {
-                if (pkt_size < INT_MAX/2) {
-                    pkt_size *= 2;
-                    av_packet_unref(avpkt);
-                    goto pkt_alloc;
-                } else
-                    return AVERROR(ENOMEM);
+        }
+
+        if (unary + 1LL + k + 32 > put_bits_left(&pb)) {
+            if (pkt_size < INT_MAX/2) {
+                pkt_size *= 2;
+                av_packet_unref(avpkt);
+                goto pkt_alloc;
+            } else
+                return AVERROR(ENOMEM);
+        }
+        while (unary) {
+            if (unary > 31) {
+                put_bits(&pb, 31, 0x7FFFFFFF);
+                unary -= 31;
+            } else {
+                put_bits(&pb, unary, (1U << unary) - 1);
+                unary = 0;
             }
-            do {
-                if (unary > 31) {
-                    put_bits(&pb, 31, 0x7FFFFFFF);
-                    unary -= 31;
-                } else {
-                    put_bits(&pb, unary, (1U << unary) - 1);
-                    unary = 0;
-                }
-            } while (unary);
         }
 
         put_bits(&pb, 1, 0);
-- 
2.54.0


>From cfb4b77946b8745209fb4439125f5090743fde3a Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Mon, 2 Nov 2026 18:49:47 +0100
Subject: [PATCH 3/7] avcodec/roqaudioenc: encode the buffered samples when
 flushed early

Encode the buffered samples once and return no packet when the buffer
is empty.

Fixes: use of uninitialized memory
Fixes: X43TLCpjYK88
Fixes: AISLE-2026-0150-00397
Use of uninitialized memory Replicated through UnModified FFmpeg with Valgrind

Found-by: Joshua Rogers (AISLE)
The fix was suggested in the report.
---
 libavcodec/roqaudioenc.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/libavcodec/roqaudioenc.c b/libavcodec/roqaudioenc.c
index 8a626c0d29f..c0e9967ab44 100644
--- a/libavcodec/roqaudioenc.c
+++ b/libavcodec/roqaudioenc.c
@@ -131,7 +131,7 @@ static int roq_dpcm_encode_frame(AVCodecContext *avctx, 
AVPacket *avpkt,
 
     stereo = (channels == 2);
 
-    if (!in && context->input_frames >= 8)
+    if (!in && (context->input_frames >= 8 || !context->buffered_samples))
         return 0;
 
     if (in && context->input_frames < 8) {
@@ -153,7 +153,7 @@ static int roq_dpcm_encode_frame(AVCodecContext *avctx, 
AVPacket *avpkt,
         context->lastSample[1] &= 0xFF00;
     }
 
-    if (context->input_frames == 7)
+    if (context->input_frames < 8)
         data_size = channels * context->buffered_samples;
     else
         data_size = channels * avctx->frame_size;
@@ -181,7 +181,7 @@ static int roq_dpcm_encode_frame(AVCodecContext *avctx, 
AVPacket *avpkt,
     avpkt->duration = data_size / channels;
 
     context->input_frames++;
-    if (!in)
+    if (!frame)
         context->input_frames = FFMAX(context->input_frames, 8);
 
     *got_packet_ptr = 1;
-- 
2.54.0


>From 15860d084159cd829f1083469649c2f0d3c462c2 Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Mon, 2 Nov 2026 18:49:47 +0100
Subject: [PATCH 4/7] avcodec/adpcmenc: encode all samples of a mono ADPCM_MS
 block with trellis

Fixes: use of uninitialized memory
Fixes: 98u4sU59NEf4
Fixes: AISLE-2026-0150-00113
Use of uninitialized memory Replicated through UnModified FFmpeg with Valgrind

Found-by: Joshua Rogers (AISLE)
---
 libavcodec/adpcmenc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libavcodec/adpcmenc.c b/libavcodec/adpcmenc.c
index cd6b330554f..fd8ce9e3670 100644
--- a/libavcodec/adpcmenc.c
+++ b/libavcodec/adpcmenc.c
@@ -782,9 +782,9 @@ static int adpcm_encode_frame(AVCodecContext *avctx, 
AVPacket *avpkt,
             if (!buf)
                 return AVERROR(ENOMEM);
             if (channels == 1) {
-                adpcm_compress_trellis(avctx, samples, buf, &c->status[0], n,
+                adpcm_compress_trellis(avctx, samples, buf, &c->status[0], 2 * 
n,
                                        channels);
-                for (int i = 0; i < n; i += 2)
+                for (int i = 0; i < 2 * n; i += 2)
                     *dst++ = (buf[i] << 4) | buf[i + 1];
             } else {
                 adpcm_compress_trellis(avctx, samples,     buf,
-- 
2.54.0


>From 2e353eb0d5ada3d8225ef2b5b12f719439fbafe8 Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Mon, 2 Nov 2026 18:49:47 +0100
Subject: [PATCH 5/7] avcodec/wavpackenc: compute the default block size in 64
 bit

Fixes: signed integer overflow
Fixes: infinite loop
Fixes: dVqGncTUAyg9
Fixes: AISLE-2026-0150-00591
Signed integer overflow and infinite loop Replicated through API with UBSAN

Found-by: Joshua Rogers (AISLE)
---
 libavcodec/wavpackenc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libavcodec/wavpackenc.c b/libavcodec/wavpackenc.c
index 17372b74a5f..e1d77b830d1 100644
--- a/libavcodec/wavpackenc.c
+++ b/libavcodec/wavpackenc.c
@@ -144,10 +144,10 @@ static av_cold int wavpack_encode_init(AVCodecContext 
*avctx)
         else
             block_samples = avctx->sample_rate;
 
-        while (block_samples * avctx->ch_layout.nb_channels > WV_MAX_SAMPLES)
+        while (block_samples * (int64_t)avctx->ch_layout.nb_channels > 
WV_MAX_SAMPLES)
             block_samples /= 2;
 
-        while (block_samples * avctx->ch_layout.nb_channels < 40000)
+        while (block_samples * (int64_t)avctx->ch_layout.nb_channels < 40000)
             block_samples *= 2;
         avctx->frame_size = block_samples;
     } else if (avctx->frame_size && (avctx->frame_size < 128 ||
-- 
2.54.0


>From 1129855549e2f6571e17134cecca350ae9ffed37 Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Mon, 2 Nov 2026 18:49:47 +0100
Subject: [PATCH 6/7] avcodec/vorbis_parser: parse the extradata only once

Fixes: Timeout
Fixes: nsq7AyzgMo4U
Fixes: AISLE-2026-0150-00507
Timeout Replicated through UnModified FFmpeg

Found-by: Joshua Rogers (AISLE)
---
 libavcodec/vorbis_parser.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavcodec/vorbis_parser.c b/libavcodec/vorbis_parser.c
index 8070004e61a..9102ae0bce6 100644
--- a/libavcodec/vorbis_parser.c
+++ b/libavcodec/vorbis_parser.c
@@ -309,7 +309,7 @@ static int vorbis_parse(AVCodecParserContext *s1, 
AVCodecContext *avctx,
     AVVorbisParseContext *s = s1->priv_data;
     int duration;
 
-    if (!s->valid_extradata && avctx->extradata && avctx->extradata_size) {
+    if (!s->extradata_parsed && avctx->extradata && avctx->extradata_size) {
         ff_vorbis_parse_init(s, avctx->extradata, avctx->extradata_size);
     }
     if (!s->valid_extradata)
-- 
2.54.0


>From d71109664f700c2347c394860d98eacb0fbba5b7 Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Mon, 2 Nov 2026 18:59:21 +0100
Subject: [PATCH 7/7] avcodec/pcm-dvdenc: pad the last frame to a whole block

24 bit samples are stored in blocks of samples_per_block samples and
the samples of an incomplete last block were dropped. Let the generic
code pad the last frame to a whole block with silence, it signals the
padding with skip samples side data so a container can mark the end.
---
 libavcodec/pcm-dvdenc.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/libavcodec/pcm-dvdenc.c b/libavcodec/pcm-dvdenc.c
index dc5224cc24c..9d4d0c9e986 100644
--- a/libavcodec/pcm-dvdenc.c
+++ b/libavcodec/pcm-dvdenc.c
@@ -25,6 +25,7 @@
 #include "bytestream.h"
 #include "codec_internal.h"
 #include "encode.h"
+#include "internal.h"
 
 typedef struct PCMDVDContext {
     uint8_t header[3];       // Header added to every frame
@@ -107,6 +108,7 @@ static av_cold int pcm_dvd_encode_init(AVCodecContext 
*avctx)
     s->header[2] = 0x80;
 
     avctx->frame_size = frame_size;
+    avctx->internal->pad_samples = s->samples_per_block;
 
     return 0;
 }
@@ -179,8 +181,7 @@ const FFCodec ff_pcm_dvd_encoder = {
     CODEC_LONG_NAME("PCM signed 16|20|24-bit big-endian for DVD-Video media"),
     .p.type         = AVMEDIA_TYPE_AUDIO,
     .p.id           = AV_CODEC_ID_PCM_DVD,
-    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME |
-                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(PCMDVDContext),
     .init           = pcm_dvd_encode_init,
     FF_CODEC_ENCODE_CB(pcm_dvd_encode_frame),
-- 
2.54.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to