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

Since f311969c03 ("avcodec/qdm2: propagate error values in the entire decoder", 
in 8.1 and later), `process_subpacket_12()` passes the still-zero `length` 
variable to `init_get_bits8()` as the buffer size, and only sets `length = 
node->packet->size * 8` after that. `synthfilt_build_sb_samples()` gets a 
non-zero `length`, so it skips its noise fallback. But its reader is empty and 
every `get_bits_left()` check fails. So for any QDM2 stream whose synthesis 
list carries a type 12 subpacket, the coded data for subbands 8 and up is never 
read, and those subbands are built from the dithering defaults. Nothing is 
logged and decoding succeeds, so the output is just wrong.

The fix initializes the reader with the packet size in bytes, the same way 
`process_subpacket_11()` does.

Verification (master 38c6f36f93, release and ASan builds):
- A small synthetic QDM2 .mov (mono, 8 packets, type 12 subpacket with 1032 
coded bits) decodes to different PCM after the fix. 15906 of 16384 samples 
change, RMS difference 39.6 LSB, which is about the RMS of the signal itself. 
Both builds are ASan-clean before and after.
- The existing `fate-qdm2` and `fate-caf-qdm2-remux` pass unchanged. The surge 
sample has no type 12 subpacket, and its decoded output is bit-identical before 
and after, which is why FATE did not catch this.
- The new `fate-qdm2-subpacket12` (test diff in the comment below; it needs a 
sample upload, so it is not in this branch yet) fails without the fix (MAXDIFF 
305) and passes with it. It needs two new files in the samples suite: 
`qdm2/subpacket12.mov` (4777 bytes) and its reference `qdm2/subpacket12.pcm` 
(32768 bytes). Both are attached. The test uses `CMP = oneoff` / `FUZZ = 2` 
like `fate-qdm2`.

This issue was found by an LLM-Enhanced Static Analysis Engine and verified 
manually.

🤖 Generated with [Claude Code](https://claude.com/claude-code)



From 94594d563c76e252c6d167b5c36ad293e1e231e4 Mon Sep 17 00:00:00 2001
From: Martin Mirchev <[email protected]>
Date: Tue, 27 Oct 2026 10:39:21 +0800
Subject: [PATCH] avcodec/qdm2: fix bit reader size in process_subpacket_12()

Since f311969c03 the GetBitContext for subpacket 12 is initialized
with the still zero "length" variable instead of the packet size, and
"length" is only set afterwards. synthfilt_build_sb_samples() then sees
a non-zero length and skips its noise fallback, but every
get_bits_left() check in it fails on the empty reader, so the coded
synthesis data of subbands 8 and above is never read and those
subbands are filled with dithering defaults instead.

Initialize the reader with the packet size, as process_subpacket_11()
does.

Fixes: f311969c03 ("avcodec/qdm2: propagate error values in the entire decoder")
Signed-off-by: Martin Mirchev <[email protected]>
---
 libavcodec/qdm2.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavcodec/qdm2.c b/libavcodec/qdm2.c
index 796321f9d8e..5b7a3c72c48 100644
--- a/libavcodec/qdm2.c
+++ b/libavcodec/qdm2.c
@@ -1098,7 +1098,7 @@ static int process_subpacket_12(QDM2Context *q, 
QDM2SubPNode *node)
     int length = 0;
 
     if (node) {
-        int ret = init_get_bits8(&gb, node->packet->data, length);
+        int ret = init_get_bits8(&gb, node->packet->data, node->packet->size);
         if (ret < 0)
             return ret;
         length = node->packet->size * 8;
-- 
2.54.0

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

Reply via email to