From a861d6f1d29c2ca3409a8fed5ad6a6f540c87a33 Mon Sep 17 00:00:00 2001 From: jeffqjiangNew <142832361+jeffqjiangNew@users.noreply.github.com> Date: Tue, 6 May 2025 12:02:51 -0400 Subject: [PATCH] Error resilience: Added a few error handling measures. (#581) * * Error resilience: Added a few error handling measures. - AV1: Added check flags to sequence header and frame header to indicate if the headers are parsed without errors. The flags are used to check if the parsing process which refers to the headers can proceed or stop. - AV1: Added divide by 0 check on tile columns in tile group parsing. - AV1: Added invalid OBU size check in AV1 elementary stream parsing in bitstream reader. - All codecs: Added divide by 0 check in display aspect ratio calculation. * * Error resilience: Fixed a typo in an error message. --- src/bit_stream_reader/es_reader.cpp | 6 +++++- src/parser/av1_defines.h | 2 ++ src/parser/av1_parser.cpp | 23 +++++++++++++++++++++-- src/parser/avc_parser.cpp | 6 ++++-- src/parser/hevc_parser.cpp | 6 ++++-- src/parser/vp9_parser.cpp | 6 ++++-- 6 files changed, 40 insertions(+), 9 deletions(-) diff --git a/src/bit_stream_reader/es_reader.cpp b/src/bit_stream_reader/es_reader.cpp index b6acbb13ee..101021a268 100644 --- a/src/bit_stream_reader/es_reader.cpp +++ b/src/bit_stream_reader/es_reader.cpp @@ -859,7 +859,7 @@ uint32_t RocVideoESParser::ReadUVLC(const uint8_t *p_stream, size_t &bit_offset) int RocVideoESParser::CheckAv1EStream(uint8_t *p_stream, int stream_size) { int score = 0; uint8_t *obu_stream = p_stream; - int curr_offset = 0; + uint32_t curr_offset = 0; int temporal_delimiter_obu_present = 0; int seq_header_obu_present = 0; int frame_header_obu_present = 0; @@ -1080,6 +1080,10 @@ int RocVideoESParser::CheckAv1EStream(uint8_t *p_stream, int stream_size) { break; } + // Check before update + if (obu_size > (stream_size - curr_offset)) { + break; + } curr_offset += obu_size; } if (syntax_error) { diff --git a/src/parser/av1_defines.h b/src/parser/av1_defines.h index e0e8c681e8..76454f834a 100644 --- a/src/parser/av1_defines.h +++ b/src/parser/av1_defines.h @@ -185,6 +185,7 @@ typedef struct { } Av1ColorConfig; typedef struct { + uint32_t is_received; uint32_t seq_profile; uint32_t still_picture; uint32_t reduced_still_picture_header; @@ -403,6 +404,7 @@ typedef struct { } Av1FilmGrainParams; typedef struct { + uint32_t is_received; uint32_t show_existing_frame; uint32_t frame_to_show_map_idx; Av1TemporalPointInfo temporal_point_info; diff --git a/src/parser/av1_parser.cpp b/src/parser/av1_parser.cpp index 7c5ec05956..e6d8c8056f 100644 --- a/src/parser/av1_parser.cpp +++ b/src/parser/av1_parser.cpp @@ -232,8 +232,10 @@ ParserResult Av1VideoParser::NotifyNewSequence(Av1SequenceHeader *p_seq_header, int disp_width = (video_format_params_.display_area.right - video_format_params_.display_area.left); int disp_height = (video_format_params_.display_area.bottom - video_format_params_.display_area.top); int gcd = std::__gcd(disp_width, disp_height); // greatest common divisor - video_format_params_.display_aspect_ratio.x = disp_width / gcd; - video_format_params_.display_aspect_ratio.y = disp_height / gcd; + if (gcd) { + video_format_params_.display_aspect_ratio.x = disp_width / gcd; + video_format_params_.display_aspect_ratio.y = disp_height / gcd; + } video_format_params_.reconfig_options = ROCDEC_RECONFIG_NEW_SURFACES; video_format_params_.video_signal_description = {0}; @@ -898,6 +900,7 @@ void Av1VideoParser::ParseSequenceHeaderObu(uint8_t *p_stream, size_t size) { if (p_seq_header->film_grain_params_present) { CheckAndAdjustDecBufPoolSize(BUFFER_POOL_MAX_SIZE * 2); } + p_seq_header->is_received = 1; } ParserResult Av1VideoParser::ParseFrameHeaderObu(uint8_t *p_stream, size_t size, int *p_bytes_parsed) { @@ -930,6 +933,12 @@ ParserResult Av1VideoParser::ParseUncompressedHeader(uint8_t *p_stream, size_t s uint32_t all_frames = (1 << NUM_REF_FRAMES) - 1; int i; + p_frame_header->is_received = 0; + if (p_seq_header->is_received == 0) { + ERR("No valid sequence header received before frame header."); + return PARSER_WRONG_STATE; + } + if (p_seq_header->frame_id_numbers_present_flag) { frame_id_len = p_seq_header->additional_frame_id_length_minus_1 + p_seq_header-> delta_frame_id_length_minus_2 + 3; } @@ -1232,6 +1241,7 @@ ParserResult Av1VideoParser::ParseUncompressedHeader(uint8_t *p_stream, size_t s FilmGrainParams(p_stream, offset, p_seq_header, p_frame_header); *p_bytes_parsed = (offset + 7) >> 3; + p_frame_header->is_received = 1; return PARSER_OK; } @@ -1246,6 +1256,11 @@ ParserResult Av1VideoParser::ParseTileGroupObu(uint8_t *p_stream, size_t size) { uint8_t *p_tg_buf = p_stream; uint32_t tg_size = size; + if (p_frame_header->is_received == 0) { + ERR("No valid frame header received before tile group."); + return PARSER_WRONG_STATE; + } + if (p_tile_group->tile_group_num == 0) { p_tile_group->buffer_ptr = p_stream; } @@ -1268,6 +1283,10 @@ ParserResult Av1VideoParser::ParseTileGroupObu(uint8_t *p_stream, size_t size) { p_tg_buf += header_bytes; tg_size -= header_bytes; for (int tile_num = p_tile_group->tg_start; tile_num <= p_tile_group->tg_end; tile_num++) { + if (tile_cols == 0) { + ERR("Tile columns is 0."); + return PARSER_WRONG_STATE; + } p_tile_group->tile_data_info[tile_num].tile_row = tile_num / tile_cols; p_tile_group->tile_data_info[tile_num].tile_col = tile_num % tile_cols; int last_tile = (tile_num == p_tile_group->tg_end); diff --git a/src/parser/avc_parser.cpp b/src/parser/avc_parser.cpp index 9ab30bd0a8..16e8eb9cc0 100644 --- a/src/parser/avc_parser.cpp +++ b/src/parser/avc_parser.cpp @@ -392,8 +392,10 @@ ParserResult AvcVideoParser::NotifyNewSps(AvcSeqParameterSet *p_sps) { int disp_width = (video_format_params_.display_area.right - video_format_params_.display_area.left) * sar.numerator; int disp_height = (video_format_params_.display_area.bottom - video_format_params_.display_area.top) * sar.denominator; int gcd = std::__gcd(disp_width, disp_height); // greatest common divisor - video_format_params_.display_aspect_ratio.x = disp_width / gcd; - video_format_params_.display_aspect_ratio.y = disp_height / gcd; + if (gcd) { + video_format_params_.display_aspect_ratio.x = disp_width / gcd; + video_format_params_.display_aspect_ratio.y = disp_height / gcd; + } video_format_params_.reconfig_options = ROCDEC_RECONFIG_NEW_SURFACES; if (p_sps->vui_parameters_present_flag) { diff --git a/src/parser/hevc_parser.cpp b/src/parser/hevc_parser.cpp index 238fab9e3c..d0f8ddd16a 100644 --- a/src/parser/hevc_parser.cpp +++ b/src/parser/hevc_parser.cpp @@ -188,8 +188,10 @@ int HevcVideoParser::FillSeqCallbackFn(HevcSeqParamSet* sps_data) { int disp_width = (video_format_params_.display_area.right - video_format_params_.display_area.left) * sar.numerator; int disp_height = (video_format_params_.display_area.bottom - video_format_params_.display_area.top) * sar.denominator; int gcd = std::__gcd(disp_width, disp_height); // greatest common divisor - video_format_params_.display_aspect_ratio.x = disp_width / gcd; - video_format_params_.display_aspect_ratio.y = disp_height / gcd; + if (gcd) { + video_format_params_.display_aspect_ratio.x = disp_width / gcd; + video_format_params_.display_aspect_ratio.y = disp_height / gcd; + } video_format_params_.reconfig_options = ROCDEC_RECONFIG_NEW_SURFACES; if (sps_data->vui_parameters_present_flag) { diff --git a/src/parser/vp9_parser.cpp b/src/parser/vp9_parser.cpp index e401e450b6..b78e974396 100644 --- a/src/parser/vp9_parser.cpp +++ b/src/parser/vp9_parser.cpp @@ -226,8 +226,10 @@ ParserResult Vp9VideoParser::NotifyNewSequence(Vp9UncompressedHeader *p_uncomp_h int disp_width = (video_format_params_.display_area.right - video_format_params_.display_area.left); int disp_height = (video_format_params_.display_area.bottom - video_format_params_.display_area.top); int gcd = std::__gcd(disp_width, disp_height); // greatest common divisor - video_format_params_.display_aspect_ratio.x = disp_width / gcd; - video_format_params_.display_aspect_ratio.y = disp_height / gcd; + if (gcd) { + video_format_params_.display_aspect_ratio.x = disp_width / gcd; + video_format_params_.display_aspect_ratio.y = disp_height / gcd; + } video_format_params_.reconfig_options = reconfig_option_; video_format_params_.video_signal_description = {0};