PR #24021 opened by Alearner12
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24021
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24021.patch
## Summary
Stop MMCO scanning when `ff_h264_pred_weight_table()` rejects a malformed
weighted-prediction syntax element. The H.264 decoder already propagates the
same helper's return value; this aligns the parser's error handling with the
decoder's established pattern.
## Problem
`scan_mmco_reset()` in `h264_parser.c` calls `ff_h264_pred_weight_table()`
but discards its return value:
```c
/* BEFORE — return value silently ignored */
if ((p->ps.pps->weighted_pred && slice_type_nos == AV_PICTURE_TYPE_P) ||
(p->ps.pps->weighted_bipred_idc == 1 && slice_type_nos ==
AV_PICTURE_TYPE_B))
ff_h264_pred_weight_table(gb, p->ps.sps, ref_count, slice_type_nos,
&pwt, p->picture_structure, logctx);
```
`ff_h264_pred_weight_table()` (in `h264_parse.c:30`) returns
`AVERROR_INVALIDDATA` via the `out_range_weight` label whenever a luma or
chroma weight/offset falls outside the valid `int8_t` range defined by the
H.264 specification (Table 7-6, section 7.4.3.2 — `pred_weight_table()`).
When that error is ignored, `scan_mmco_reset()` continues to read
`adaptive_ref_pic_marking_mode_flag` from a `GetBitContext` that is now
positioned at an **unknown offset** within the partially consumed weight table.
The MMCO scanner's invariant — that the bitreader sits immediately after a
fully parsed `pred_weight_table()` — is violated, so subsequent bit reads
interpret corrupted slice data as MMCO commands.
### Concrete trigger
A crafted P-slice with `weighted_pred_flag = 1` and a luma weight value
outside `[-128, 127]` (e.g. `luma_weight_l0[0] = 200`) causes
`ff_h264_pred_weight_table()` to return `AVERROR_INVALIDDATA` after logging
`"Out of range weight"`. Without this patch, the parser proceeds to read
`adaptive_ref_pic_marking_mode_flag` from the wrong position in the bitstream.
## Fix
Capture the return value and propagate it before attempting MMCO scanning:
```c
/* AFTER */
if ((p->ps.pps->weighted_pred && slice_type_nos == AV_PICTURE_TYPE_P) ||
(p->ps.pps->weighted_bipred_idc == 1 && slice_type_nos ==
AV_PICTURE_TYPE_B)) {
ret = ff_h264_pred_weight_table(gb, p->ps.sps, ref_count, slice_type_nos,
&pwt, p->picture_structure, logctx);
if (ret < 0)
return ret;
}
```
The decoder path in `h264_slice.c` already handles the same call identically:
```c
/* h264_slice.c — existing pattern this patch mirrors */
ret = ff_h264_pred_weight_table(&sl->gb, sps, sl->ref_count,
sl->slice_type_nos, &sl->pwt,
sl->picture_structure, h->avctx);
if (ret < 0)
return ret;
```
## Spec reference
ITU-T H.264 (08/2021), section 7.3.3.2 — `pred_weight_table()` syntax;
section 7.4.3.2 — semantics. Weight and offset values must satisfy
`-2^(luma_log2_weight_denom+6) ≤ luma_weight_l0[ i ] <
2^(luma_log2_weight_denom+6)`.
Values outside that range are non-conforming; the parser must not
consume further slice data as though the table parsed correctly.
## Variant analysis
The analogous parsers for HEVC (`hevc_parse.c`) and AV1 (`av1_parse.c`) do
not have a `pred_weight_table` call in their MMCO-equivalent scanner paths.
VVC and EVC parsers were checked and are clean. This defect is specific to the
H.264 parser because weighted prediction and MMCO are both slice-header
features unique to H.264.
## Compatibility and performance
Valid streams are unchanged. Only malformed slices with out-of-range weight
values stop metadata scanning earlier than before, which is the correct
behavior. The successful path adds one predictable conditional branch with no
meaningful performance impact.
## Testing
`libavcodec/h264_parser.o` compiles successfully in a Clang ASan/UBSan build
with the H.264 parser enabled:
```sh
make -j$(nproc) libavcodec/h264_parser.o
ASAN_OPTIONS=detect_leaks=0 \
UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=0 \
make -j$(nproc) fate-h264-parser
```
The existing `fate-h264-parser` regression (added in the preceding VUI timing
fix) continues to pass. A FATE test specifically exercising the out-of-range
weight path is not included because constructing a valid Annex-B stream that
reaches this error without the decoder aborting at an earlier check requires
decoder-level infrastructure beyond the scope of a parser-only fix; the
defensive error check is directly observable in the source and matches the
pattern already used in `h264_slice.c`.
From fc4dbe09d93f4a47f11f68e3fe682353d1314b82 Mon Sep 17 00:00:00 2001
From: Alearner12 <[email protected]>
Date: Wed, 5 Aug 2026 20:11:04 +0530
Subject: [PATCH] avcodec/h264_parser: propagate pred_weight_table errors
---
libavcodec/h264_parser.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/libavcodec/h264_parser.c b/libavcodec/h264_parser.c
index 9d64fc603f..207cdd428e 100644
--- a/libavcodec/h264_parser.c
+++ b/libavcodec/h264_parser.c
@@ -176,7 +176,7 @@ static int scan_mmco_reset(AVCodecParserContext *s,
GetBitContext *gb,
H264PredWeightTable pwt;
int slice_type_nos = s->pict_type & 3;
H264ParseContext *p = s->priv_data;
- int list_count, ref_count[2];
+ int list_count, ref_count[2], ret;
if (p->ps.pps->redundant_pic_cnt_present)
@@ -218,9 +218,12 @@ static int scan_mmco_reset(AVCodecParserContext *s,
GetBitContext *gb,
}
if ((p->ps.pps->weighted_pred && slice_type_nos == AV_PICTURE_TYPE_P) ||
- (p->ps.pps->weighted_bipred_idc == 1 && slice_type_nos ==
AV_PICTURE_TYPE_B))
- ff_h264_pred_weight_table(gb, p->ps.sps, ref_count, slice_type_nos,
- &pwt, p->picture_structure, logctx);
+ (p->ps.pps->weighted_bipred_idc == 1 && slice_type_nos ==
AV_PICTURE_TYPE_B)) {
+ ret = ff_h264_pred_weight_table(gb, p->ps.sps, ref_count,
slice_type_nos,
+ &pwt, p->picture_structure, logctx);
+ if (ret < 0)
+ return ret;
+ }
if (get_bits1(gb)) { // adaptive_ref_pic_marking_mode_flag
int i;
--
2.52.0
_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]