From bcaab3609805ea10fb3d9ac0c9d947b4c3563948 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Sat, 15 Mar 2025 23:48:52 +0900 Subject: [PATCH 2/2] h265parser: Fix num_long_term_pics bound check As defined in the spec 7.4.7.1, calculates allowed maximum value of num_long_term_pics Fixes ZDI-CAN-26596 Fixes: https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/4285 Part-of: Upstream-Status: Backport [https://gitlab.freedesktop.org/gstreamer/gstreamer/-/commit/bcaab3609805ea10fb3d9ac0c9d947b4c3563948] CVE: CVE-2025-3887 Signed-off-by: Vijay Anusuri --- gst-libs/gst/codecparsers/gsth265parser.c | 40 +++++++++++++++++++++-- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/gst-libs/gst/codecparsers/gsth265parser.c b/gst-libs/gst/codecparsers/gsth265parser.c index d02e32d..ad9751f 100644 --- a/gst-libs/gst/codecparsers/gsth265parser.c +++ b/gst-libs/gst/codecparsers/gsth265parser.c @@ -2513,6 +2513,8 @@ gst_h265_parser_parse_slice_hdr (GstH265Parser * parser, READ_UINT8 (&nr, slice->colour_plane_id, 2); if (!GST_H265_IS_NAL_TYPE_IDR (nalu->type)) { + const GstH265ShortTermRefPicSet *ref_pic_sets = NULL; + READ_UINT16 (&nr, slice->pic_order_cnt_lsb, (sps->log2_max_pic_order_cnt_lsb_minus4 + 4)); @@ -2525,21 +2527,53 @@ gst_h265_parser_parse_slice_hdr (GstH265Parser * parser, goto error; slice->short_term_ref_pic_set_size = nal_reader_get_pos (&nr) - pos; + + ref_pic_sets = &slice->short_term_ref_pic_sets; } else if (sps->num_short_term_ref_pic_sets > 1) { const guint n = ceil_log2 (sps->num_short_term_ref_pic_sets); READ_UINT8 (&nr, slice->short_term_ref_pic_set_idx, n); CHECK_ALLOWED_MAX (slice->short_term_ref_pic_set_idx, sps->num_short_term_ref_pic_sets - 1); + ref_pic_sets = + &sps->short_term_ref_pic_set[slice->short_term_ref_pic_set_idx]; + } else { + ref_pic_sets = &sps->short_term_ref_pic_set[0]; } if (sps->long_term_ref_pics_present_flag) { guint32 limit; + gint max_num_long_term_pics = 0; + gint TwoVersionsOfCurrDecPicFlag = 0; - if (sps->num_long_term_ref_pics_sps > 0) + if (sps->num_long_term_ref_pics_sps > 0) { READ_UE_MAX (&nr, slice->num_long_term_sps, sps->num_long_term_ref_pics_sps); - - READ_UE_MAX (&nr, slice->num_long_term_pics, 16); + } + + /* 7.4.3.3.3 */ + if (pps->pps_scc_extension_flag && + pps->pps_scc_extension_params.pps_curr_pic_ref_enabled_flag && + (sps->sample_adaptive_offset_enabled_flag || + !pps->deblocking_filter_disabled_flag || + pps->deblocking_filter_override_enabled_flag)) { + TwoVersionsOfCurrDecPicFlag = 1; + } + + /* Calculated upper bound num_long_term_pics can have. 7.4.7.1 */ + max_num_long_term_pics = + /* sps_max_dec_pic_buffering_minus1[TemporalId], allowed max is + * MaxDpbSize - 1 */ + MAX_DPB_SIZE - 1 + - (gint) slice->num_long_term_sps + - (gint) ref_pic_sets->NumNegativePics + - (gint) ref_pic_sets->NumPositivePics - + TwoVersionsOfCurrDecPicFlag; + if (max_num_long_term_pics < 0) { + GST_WARNING ("Invalid stream, too many reference pictures"); + goto error; + } + + READ_UE_MAX (&nr, slice->num_long_term_pics, max_num_long_term_pics); limit = slice->num_long_term_sps + slice->num_long_term_pics; for (i = 0; i < limit; i++) { if (i < slice->num_long_term_sps) { -- 2.25.1