Commit a35c879992 for ffmpeg
commit a35c8799920a93b99781eab6e70a5795ee7d182b
Author: Michael Niedermayer <michael@niedermayer.cc>
Date: Mon Sep 21 23:36:48 2026 +0200
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 <2388969553@qq.com>
Fixes: ZAKu08c7UMiZ
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
}