PR #25338 opened by Daniel Brodie (danielbrodie)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25338
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25338.patch

# Summary of changes

Two NotchLC-only fixes, one commit each:

- `avcodec/notchlc: read format 2 payloads after the header` fixes #25283. For 
format 2, gb still covered the whole packet, so every offset from the payload 
header was applied 16 bytes early.
- `avcodec/notchlc: treat an empty alpha control-word section as no alpha` 
fixes #25281. RGB-only exports leave that section empty (uv_data_offset == 
a_control_word_offset) but carry nonzero a_data_offset and a_count_size, so the 
existing test took the alpha path and every frame failed.

Tested on master adfe258a6a:
- the samples attached to #25281 and #25283 now decode every frame (before: 
none);
- the full 300-frame exports they were cut from decode 300/300 frames; the 
format 2 version is framemd5-identical to the LZ4 original, and the RGB-only 
export decodes with opaque alpha;
- make fate (Windows, MSYS2 MINGW64, full fate-suite): the 15 failures also 
fail on unpatched master;
- 200 decodes of damaged copies (random byte changes inside mdat) gave no 
crashes or hangs.

AI disclosure: AI was used for investigation and development of these patches.


>From 693c95f5889139e792ffc8d23bd3d74c92ffbcbc Mon Sep 17 00:00:00 2001
From: Daniel Brodie <[email protected]>
Date: Wed, 21 Oct 2026 14:43:02 -0400
Subject: [PATCH 1/2] avcodec/notchlc: read format 2 payloads after the header

Format 2 stores the payload uncompressed after the 16-byte header, but gb
was left covering the whole packet, so every offset read from the payload
header was applied 16 bytes early and decoding failed.

Fixes: #25283
Signed-off-by: Daniel Brodie <[email protected]>
---
 libavcodec/notchlc.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/libavcodec/notchlc.c b/libavcodec/notchlc.c
index 396089254e6..577a955c445 100644
--- a/libavcodec/notchlc.c
+++ b/libavcodec/notchlc.c
@@ -519,6 +519,11 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *p,
             return AVERROR_INVALIDDATA;
 
         bytestream2_init(gb, s->uncompressed_buffer, uncompressed_size);
+    } else {
+        if (bytestream2_get_bytes_left(gb) < uncompressed_size)
+            return AVERROR_INVALIDDATA;
+
+        bytestream2_init(gb, avpkt->data + bytestream2_tell(gb), 
uncompressed_size);
     }
 
     ret = decode_blocks(avctx, p, uncompressed_size);
-- 
2.54.0


>From b8e080b39f39866cb0b26a463cb726b3597bb028 Mon Sep 17 00:00:00 2001
From: Daniel Brodie <[email protected]>
Date: Wed, 21 Oct 2026 14:43:03 -0400
Subject: [PATCH 2/2] avcodec/notchlc: treat an empty alpha control-word
 section as no alpha

RGB-only files from the NotchLC After Effects exporter leave the alpha
control-word section empty (uv_data_offset == a_control_word_offset) but
carry nonzero a_data_offset and a_count_size, so the existing test took
the alpha path and every frame failed.

Fixes: #25281
Signed-off-by: Daniel Brodie <[email protected]>
---
 libavcodec/notchlc.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/libavcodec/notchlc.c b/libavcodec/notchlc.c
index 577a955c445..205cbeed8a3 100644
--- a/libavcodec/notchlc.c
+++ b/libavcodec/notchlc.c
@@ -284,7 +284,8 @@ static int decode_blocks(AVCodecContext *avctx, AVFrame *p,
     rgb = *gb;
     dgb = *gb;
     bytestream2_seek(gb, s->a_control_word_offset, SEEK_SET);
-    if (s->uv_count_offset == s->a_control_word_offset) {
+    if (s->uv_count_offset == s->a_control_word_offset ||
+        s->uv_data_offset  == s->a_control_word_offset) {
         for (int y = 0; y < avctx->height; y++) {
             for (int x = 0; x < avctx->width; x++)
                 dsta[x] = 4095;
-- 
2.54.0

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

Reply via email to