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

copy_bits() silently writes nothing when the requested bits do not fit
the 256 byte superframe cache or exceed what is left in the packet, but
sframe_cache_size was set to the requested count regardless. On the next
packet the spillover bits were then appended at offset 0 and decoded as
a superframe of their own, or with no spillover, stale bytes from an
earlier packet were decoded again.

Use put_bits_count() so the size always matches the cache content. A
leftover larger than the cache is dropped instead, which is correct: a
speech superframe never needs more than about 1300 bits, so such a
leftover cannot be one. Bit reads never left sframe_cache, so this is
not a memory safety issue; the bogus superframes and the decoder errors
they produced on the affected samples are gone.

Using put_bits_count() for the size was suggested by the reporter.

Found-by: zhang xingxing <[email protected]>
Fixes: ZAKu08c7UMiZ



>From 770640b458e58f73e61c36015f308a1ec3ee5065 Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Mon, 21 Sep 2026 23:36:48 +0200
Subject: [PATCH] avcodec/wmavoice: set sframe_cache_size to the number of bits
 actually cached

copy_bits() silently writes nothing when the requested bits do not fit
the 256 byte superframe cache or exceed what is left in the packet, but
sframe_cache_size was set to the requested count regardless. On the next
packet the spillover bits were then appended at offset 0 and decoded as
a superframe of their own, or with no spillover, stale bytes from an
earlier packet were decoded again.

Use put_bits_count() so the size always matches the cache content. A
leftover larger than the cache is dropped instead, which is correct: a
speech superframe never needs more than about 1300 bits, so such a
leftover cannot be one. Bit reads never left sframe_cache, so this is
not a memory safety issue; the bogus superframes and the decoder errors
they produced on the affected samples are gone.

Using put_bits_count() for the size was suggested by the reporter.

Found-by: zhang xingxing <[email protected]>
Fixes: ZAKu08c7UMiZ
---
 libavcodec/wmavoice.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/libavcodec/wmavoice.c b/libavcodec/wmavoice.c
index 7fc735ad1d..c3cd053ba9 100644
--- a/libavcodec/wmavoice.c
+++ b/libavcodec/wmavoice.c
@@ -1960,8 +1960,8 @@ static int wmavoice_decode_packet(AVCodecContext *ctx, 
AVFrame *frame,
                 s->spillover_nbits = avpkt->size * 8 - cnt;
             }
             copy_bits(&s->pb, buf, size, gb, s->spillover_nbits);
+            s->sframe_cache_size = put_bits_count(&s->pb);
             flush_put_bits(&s->pb);
-            s->sframe_cache_size += s->spillover_nbits;
             if ((res = synth_superframe(ctx, frame, got_frame_ptr)) == 0 &&
                 *got_frame_ptr) {
                 cnt += s->spillover_nbits;
@@ -1993,10 +1993,11 @@ static int wmavoice_decode_packet(AVCodecContext *ctx, 
AVFrame *frame,
             res = cnt >> 3;
             return res;
         }
-    } else if ((s->sframe_cache_size = pos) > 0) {
+    } else if (pos > 0) {
         /* ... cache it for spillover in next packet */
         init_put_bits(&s->pb, s->sframe_cache, SFRAME_CACHE_MAXSIZE);
-        copy_bits(&s->pb, buf, size, gb, s->sframe_cache_size);
+        copy_bits(&s->pb, buf, size, gb, pos);
+        s->sframe_cache_size = put_bits_count(&s->pb);
         // FIXME bad - just copy bytes as whole and add use the
         // skip_bits_next field
     }
-- 
2.52.0

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

Reply via email to