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

# Backport to release/9.0: avcodec/h264dec: do not add 0 to the NULL plane 
pointers when filling a missing field

## Why

`finalize_frame()` can take the "duplicate the missing field" recovery path
while decoding an H.264 stream.  That path computes plane pointers for all
four planes, but planes the pixel format does not use have
`f->data[p] == NULL` and `f->linesize[p] == 0`, so the expression evaluates
`NULL + 0`, which is pointer-overflow undefined behaviour.  A sanitizer build
aborts:

```text
libavcodec/h264dec.c:951:42: runtime error: applying zero offset to null pointer
    #0 finalize_frame                   libavcodec/h264dec.c:951:42
    #1 h264_decode_frame                libavcodec/h264dec.c:1076:19
    #2 decode_simple_internal           libavcodec/decode.c:457:16
    #3 decode_simple_receive_frame      libavcodec/decode.c:617:15
    #4 ff_decode_receive_frame_internal libavcodec/decode.c:653:15
    #5 decode_receive_frame_internal    libavcodec/decode.c:671:15
    #6 avcodec_send_packet              libavcodec/decode.c:755:15
    #7 LLVMFuzzerTestOneInput           tools/target_dec_fuzzer.c:576:25
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior 
libavcodec/h264dec.c:951:42 in
```

master already fixes exactly this hunk (`4a511dc8`, "Not a vulnerability");
`release/9.0` does not.

## Change

Plain cherry-pick of `4a511dc8` onto `release/9.0` — only the hunk offset
differs.  `FF_PTR_ADD()` returns the pointer unchanged for a zero offset, so no
arithmetic is performed on `NULL`, and the values handed to `av_image_copy()`
are identical for every input.

## Validation

Built `tools/target_dec_h264_fuzzer` from the 9.0 release sources
(`RELEASE`/`VERSION` = 9.0) with clang 12 and `-fsanitize=address,undefined`,
`--disable-asm`, and replayed the same 419-byte input
(sha256 `2058c244cc9e9af2aeb8d19ac8c3b5a332d7374294b1b018530f2d30e19b8bba`)
that produced the report.

Before (unpatched `release/9.0`, exit code 1):

```text
$ ./target_dec_h264_fuzzer -runs=1 poc
Running: poc
libavcodec/h264dec.c:951:42: runtime error: applying zero offset to null pointer
    #0 0x60d1f0 in finalize_frame libavcodec/h264dec.c:951:42
    #1 0x6053cd in h264_decode_frame libavcodec/h264dec.c:1076:19
    #2 0x5d993e in decode_simple_internal libavcodec/decode.c:457:16
    #3 0x5c7804 in decode_simple_receive_frame libavcodec/decode.c:617:15
    #4 0x5c552b in ff_decode_receive_frame_internal libavcodec/decode.c:653:15
    #5 0x5c829d in decode_receive_frame_internal libavcodec/decode.c:671:15
    #6 0x5c7ec5 in avcodec_send_packet libavcodec/decode.c:755:15
    #7 0x5abd13 in LLVMFuzzerTestOneInput tools/target_dec_fuzzer.c:576:25
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior 
libavcodec/h264dec.c:951:42 in
```

After (`release/9.0` + this patch, exit code 0, no diagnostic, input still
decoded):

```text
$ ./target_dec_h264_fuzzer -runs=1 poc
Running: poc
Executed poc in 15 ms
***
*** NOTE: fuzzing was not performed, you have only
***       executed the target code on a fixed set of inputs.
***
```

## Note

I am not claiming a vulnerability — upstream classified this as "not a
vulnerability".  The question is only whether the master fix can be carried
into `release/9.0`, in the same way the very similar `51c4a23d74a`
("avcodec/opus/dec: only add offsets to valid channel pointers", same
clang-ubsan null pointer symptom) was cherry-picked there on 2026-09-25.



From c2270420a20c8c9509ca9e15bccab9583fe5e6ce Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Sat, 19 Sep 2026 22:16:35 +0200
Subject: [PATCH] avcodec/h264dec: do not add 0 to the NULL plane pointers when
 filling a missing field

Not a vulnerability

Fixes: irADzptPLJF2
Found-by: Qiang Li <[email protected]>
(cherry picked from commit 4a511dc8eba349b43817e49661b28d521c6b604a)
Signed-off-by: iceray <[email protected]>
---
 libavcodec/h264dec.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c
index ca65df2b84..1f055345c2 100644
--- a/libavcodec/h264dec.c
+++ b/libavcodec/h264dec.c
@@ -948,8 +948,8 @@ static int finalize_frame(H264Context *h, AVFrame *dst, 
H264Picture *out, int *g
             av_log(h->avctx, AV_LOG_DEBUG, "Duplicating field %d to fill 
missing\n", field);
 
             for (p = 0; p<4; p++) {
-                dst_data[p] = f->data[p] + (field^1)*f->linesize[p];
-                src_data[p] = f->data[p] +  field   *f->linesize[p];
+                dst_data[p] = FF_PTR_ADD(f->data[p], (field^1)*f->linesize[p]);
+                src_data[p] = FF_PTR_ADD(f->data[p],  field   *f->linesize[p]);
                 linesizes[p] = 2*f->linesize[p];
             }
 
-- 
2.52.0

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

Reply via email to