PR #23278 opened by michaelni URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23278 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23278.patch
H265RawVPS embedded hrd_parameters as an inline array of HEVC_MAX_LAYER_SETS (1024) H265RawHRDParameters, making the structure roughly 7.9 MB. CBS allocates the whole content structure for every VPS NAL unit before parsing it, so a packet consisting of many tiny VPS NALs forces gigabytes of allocations and triggers an out-of-memory condition. Allocate hrd_parameters separately, sized to vps_num_hrd_parameters, backed by an AVBufferRef registered as a second internal reference offset on the VPS unit type. This shrinks the resident structure to tens of kilobytes and bounds the hrd_parameters allocation by the amount that is actually parsed. Fixes: 472754452/clusterfuzz-testcase-minimized-ffmpeg_BSF_HEVC_METADATA_fuzzer-6379024978083840 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer <[email protected]> >From 6284a60781186f3ea9cd603da4c3c724e84868ca Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Sat, 30 May 2026 05:12:22 +0200 Subject: [PATCH] avcodec/cbs_h265: allocate VPS hrd_parameters dynamically H265RawVPS embedded hrd_parameters as an inline array of HEVC_MAX_LAYER_SETS (1024) H265RawHRDParameters, making the structure roughly 7.9 MB. CBS allocates the whole content structure for every VPS NAL unit before parsing it, so a packet consisting of many tiny VPS NALs forces gigabytes of allocations and triggers an out-of-memory condition. Allocate hrd_parameters separately, sized to vps_num_hrd_parameters, backed by an AVBufferRef registered as a second internal reference offset on the VPS unit type. This shrinks the resident structure to tens of kilobytes and bounds the hrd_parameters allocation by the amount that is actually parsed. Fixes: 472754452/clusterfuzz-testcase-minimized-ffmpeg_BSF_HEVC_METADATA_fuzzer-6379024978083840 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer <[email protected]> --- libavcodec/cbs_h265.c | 5 +++-- libavcodec/cbs_h265.h | 3 ++- libavcodec/cbs_h265_syntax_template.c | 4 ++++ libavcodec/cbs_internal.h | 10 ++++++++++ 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/libavcodec/cbs_h265.c b/libavcodec/cbs_h265.c index 21df609d08..5f46cda1f6 100644 --- a/libavcodec/cbs_h265.c +++ b/libavcodec/cbs_h265.c @@ -142,7 +142,7 @@ static int FUNC_H265(name) args AV_INPUT_BUFFER_PADDING_SIZE); \ if (!name ## _ref) \ return AVERROR(ENOMEM); \ - name = name ## _ref->data; \ + name = (void *)name ## _ref->data; \ } while (0) #define FUNC(name) FUNC_H265(name) @@ -715,7 +715,8 @@ static void cbs_h265_free_sei(AVRefStructOpaque unused, void *content) } static CodedBitstreamUnitTypeDescriptor cbs_h265_unit_types[] = { - CBS_UNIT_TYPE_INTERNAL_REF(HEVC_NAL_VPS, H265RawVPS, extension_data.data), + CBS_UNIT_TYPE_INTERNAL_REF_2(HEVC_NAL_VPS, H265RawVPS, extension_data.data, + hrd_parameters), CBS_UNIT_TYPE_INTERNAL_REF(HEVC_NAL_SPS, H265RawSPS, extension_data.data), CBS_UNIT_TYPE_INTERNAL_REF(HEVC_NAL_PPS, H265RawPPS, extension_data.data), diff --git a/libavcodec/cbs_h265.h b/libavcodec/cbs_h265.h index bb7a29c2e5..cd84b7b594 100644 --- a/libavcodec/cbs_h265.h +++ b/libavcodec/cbs_h265.h @@ -211,7 +211,8 @@ typedef struct H265RawVPS { uint16_t vps_num_hrd_parameters; uint16_t hrd_layer_set_idx[HEVC_MAX_LAYER_SETS]; uint8_t cprms_present_flag[HEVC_MAX_LAYER_SETS]; - H265RawHRDParameters hrd_parameters[HEVC_MAX_LAYER_SETS]; + H265RawHRDParameters *hrd_parameters; + AVBufferRef *hrd_parameters_ref; uint8_t vps_extension_flag; H265RawExtensionData extension_data; diff --git a/libavcodec/cbs_h265_syntax_template.c b/libavcodec/cbs_h265_syntax_template.c index 2842c40585..c97b7ed361 100644 --- a/libavcodec/cbs_h265_syntax_template.c +++ b/libavcodec/cbs_h265_syntax_template.c @@ -489,6 +489,10 @@ static int FUNC(vps)(CodedBitstreamContext *ctx, RWContext *rw, if (current->vps_poc_proportional_to_timing_flag) ue(vps_num_ticks_poc_diff_one_minus1, 0, UINT32_MAX - 1); ue(vps_num_hrd_parameters, 0, current->vps_num_layer_sets_minus1 + 1); + if (current->vps_num_hrd_parameters > 0) + allocate(current->hrd_parameters, + current->vps_num_hrd_parameters * + sizeof(*current->hrd_parameters)); for (i = 0; i < current->vps_num_hrd_parameters; i++) { ues(hrd_layer_set_idx[i], current->vps_base_layer_internal_flag ? 0 : 1, diff --git a/libavcodec/cbs_internal.h b/libavcodec/cbs_internal.h index 2af8075f78..f872efea74 100644 --- a/libavcodec/cbs_internal.h +++ b/libavcodec/cbs_internal.h @@ -366,6 +366,16 @@ int CBS_FUNC(write_signed)(CodedBitstreamContext *ctx, PutBitContext *pbc, #define CBS_UNIT_TYPE_INTERNAL_REF(type, structure, ref_field) \ CBS_UNIT_TYPES_INTERNAL_REF((type), structure, ref_field) +#define CBS_UNIT_TYPE_INTERNAL_REF_2(type_, structure, ref_field0, ref_field1) { \ + .nb_unit_types = 1, \ + .unit_type.list = { type_ }, \ + .content_type = CBS_CONTENT_TYPE_INTERNAL_REFS, \ + .content_size = sizeof(structure), \ + .type.ref = { .nb_offsets = 2, \ + .offsets = { offsetof(structure, ref_field0), \ + offsetof(structure, ref_field1) } }, \ + } + #define CBS_UNIT_RANGE_INTERNAL_REF(range_start, range_end, structure, ref_field) { \ .nb_unit_types = CBS_UNIT_TYPE_RANGE, \ .unit_type.range.start = range_start, \ -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
