From 589d21b8a316ebc12d82b64d342ea90da152ad05 Mon Sep 17 00:00:00 2001 From: Ramesh Katuri Date: Fri, 28 Sep 2018 17:58:53 +0530 Subject: [PATCH 1/8] Fix for OOB write in mpeg-d drc bit stream parsing by adding bound checks Added bound checks for all the parameters which are derived from bit stream. Bug:116760188 Bug:116019594 Bug:116114402 Test: vendor Change-Id: I126cd520e7faf2281ab731da559b11c74a9e30b5 --- decoder/drc_src/impd_drc_dynamic_payload.c | 21 +++++++++++- ...d_drc_selection_process_drcset_selection.c | 18 +++++++--- decoder/drc_src/impd_drc_static_payload.c | 33 +++++++++++++++++++ 3 files changed, 67 insertions(+), 5 deletions(-) diff --git a/decoder/drc_src/impd_drc_dynamic_payload.c b/decoder/drc_src/impd_drc_dynamic_payload.c index 3c5e0cb..9ed26d2 100644 --- a/decoder/drc_src/impd_drc_dynamic_payload.c +++ b/decoder/drc_src/impd_drc_dynamic_payload.c @@ -536,6 +536,9 @@ WORD32 impd_parse_drc_ext_v1(ia_bit_buf_struct* it_bit_buff, if (dwnmix_instructions_v1_flag == 1) { dwnmix_instructions_v1_count = impd_read_bits_buf(it_bit_buff, 7); if (it_bit_buff->error) return it_bit_buff->error; + if ((dwnmix_instructions_v1_count + drc_config->dwnmix_instructions_count) > + DOWNMIX_INSTRUCTION_COUNT_MAX) + return UNEXPECTED_ERROR; for (i = 0; i < dwnmix_instructions_v1_count; i++) { err = impd_parse_dwnmix_instructions( it_bit_buff, version, ia_drc_params_struct, @@ -591,6 +594,9 @@ WORD32 impd_parse_drc_ext_v1(ia_bit_buf_struct* it_bit_buff, return UNEXPECTED_ERROR; if (it_bit_buff->error) return it_bit_buff->error; + if (str_drc_config_ext->loud_eq_instructions_count > + LOUD_EQ_INSTRUCTIONS_COUNT_MAX) + return UNEXPECTED_ERROR; for (i = 0; i < str_drc_config_ext->loud_eq_instructions_count; i++) { err = impd_parse_loud_eq_instructions( it_bit_buff, &str_drc_config_ext->loud_eq_instructions[i]); @@ -939,6 +945,8 @@ WORD32 impd_parse_eq_coefficients(ia_bit_buf_struct* it_bit_buff, str_eq_coeff->unique_td_filter_element_count = impd_read_bits_buf(it_bit_buff, 6); + if (str_eq_coeff->unique_td_filter_element_count > FILTER_ELEMENT_COUNT_MAX) + return (UNEXPECTED_ERROR); if (it_bit_buff->error) return it_bit_buff->error; err = impd_parse_unique_td_filt_ele( @@ -948,6 +956,9 @@ WORD32 impd_parse_eq_coefficients(ia_bit_buf_struct* it_bit_buff, str_eq_coeff->unique_eq_subband_gains_count = impd_read_bits_buf(it_bit_buff, 6); + if (str_eq_coeff->unique_eq_subband_gains_count > + UNIQUE_SUBBAND_GAIN_COUNT_MAX) + return (UNEXPECTED_ERROR); if (it_bit_buff->error) return it_bit_buff->error; if (str_eq_coeff->unique_eq_subband_gains_count > 0) { @@ -1078,6 +1089,9 @@ WORD32 impd_parse_eq_instructions( additional_dmix_id_cnt = impd_read_bits_buf(it_bit_buff, 7); if (it_bit_buff->error) return it_bit_buff->error; + if (additional_dmix_id_cnt >= DOWNMIX_ID_COUNT_MAX) + return UNEXPECTED_ERROR; + for (i = 1; i < additional_dmix_id_cnt + 1; i++) { str_eq_instructions->downmix_id[i] = impd_read_bits_buf(it_bit_buff, 7); if (it_bit_buff->error) return it_bit_buff->error; @@ -1099,6 +1113,8 @@ WORD32 impd_parse_eq_instructions( if (additional_drc_set_id_present) { additional_drc_set_id_cnt = impd_read_bits_buf(it_bit_buff, 6); if (it_bit_buff->error) return it_bit_buff->error; + if (additional_drc_set_id_cnt >= DRC_SET_ID_COUNT_MAX) + return UNEXPECTED_ERROR; for (i = 1; i < additional_drc_set_id_cnt + 1; i++) { str_eq_instructions->drc_set_id[i] = impd_read_bits_buf(it_bit_buff, 6); @@ -1238,7 +1254,8 @@ WORD32 impd_parse_loud_eq_instructions( if (additional_dmix_id_present) { additional_dmix_id_cnt = impd_read_bits_buf(it_bit_buff, 7); if (it_bit_buff->error) return it_bit_buff->error; - + if (additional_dmix_id_cnt >= DOWNMIX_ID_COUNT_MAX) + return UNEXPECTED_ERROR; for (i = 1; i < additional_dmix_id_cnt + 1; i++) { loud_eq_instructions->downmix_id[i] = impd_read_bits_buf(it_bit_buff, 7); @@ -1265,6 +1282,8 @@ WORD32 impd_parse_loud_eq_instructions( if (additional_drc_set_id_present) { additional_drc_set_id_cnt = impd_read_bits_buf(it_bit_buff, 6); if (it_bit_buff->error) return it_bit_buff->error; + if ((additional_drc_set_id_cnt >= DRC_SET_ID_COUNT_MAX)) + return UNEXPECTED_ERROR; for (i = 1; i < additional_drc_set_id_cnt + 1; i++) { loud_eq_instructions->drc_set_id[i] = diff --git a/decoder/drc_src/impd_drc_selection_process_drcset_selection.c b/decoder/drc_src/impd_drc_selection_process_drcset_selection.c index f05eceb..b91df9a 100644 --- a/decoder/drc_src/impd_drc_selection_process_drcset_selection.c +++ b/decoder/drc_src/impd_drc_selection_process_drcset_selection.c @@ -305,6 +305,7 @@ WORD32 impd_select_drcs_without_compr_effects( } } if (match == 1) { + if (k >= SELECTION_CANDIDATE_COUNT_MAX) return UNEXPECTED_ERROR; memcpy(&selection_candidate_info_step_2[k], &selection_candidate_info[i], sizeof(ia_selection_candidate_info_struct)); k++; @@ -365,6 +366,7 @@ WORD32 impd_match_effect_type_attempt( 0x0) || ((drc_instructions_dependent->drc_set_effect & effect_bit_idx) != 0x0)) { + if (k >= SELECTION_CANDIDATE_COUNT_MAX) return UNEXPECTED_ERROR; memcpy(&selection_candidate_info_step_2[k], &selection_candidate_info[i], sizeof(ia_selection_candidate_info_struct)); @@ -375,6 +377,7 @@ WORD32 impd_match_effect_type_attempt( 0x0) && ((drc_instructions_dependent->drc_set_effect & effect_bit_idx) == 0x0)) { + if (k >= SELECTION_CANDIDATE_COUNT_MAX) return UNEXPECTED_ERROR; memcpy(&selection_candidate_info_step_2[k], &selection_candidate_info[i], sizeof(ia_selection_candidate_info_struct)); @@ -385,6 +388,7 @@ WORD32 impd_match_effect_type_attempt( if (state_requested == 1) { if ((str_drc_instruction_str->drc_set_effect & effect_bit_idx) != 0x0) { + if (k >= SELECTION_CANDIDATE_COUNT_MAX) return UNEXPECTED_ERROR; memcpy(&selection_candidate_info_step_2[k], &selection_candidate_info[i], sizeof(ia_selection_candidate_info_struct)); @@ -393,6 +397,7 @@ WORD32 impd_match_effect_type_attempt( } else { if ((str_drc_instruction_str->drc_set_effect & effect_bit_idx) == 0x0) { + if (k >= SELECTION_CANDIDATE_COUNT_MAX) return UNEXPECTED_ERROR; memcpy(&selection_candidate_info_step_2[k], &selection_candidate_info[i], sizeof(ia_selection_candidate_info_struct)); @@ -511,6 +516,7 @@ WORD32 impd_match_dynamic_range( if (requested_dyn_range_range_flag == 1) { if ((lp_avg_val >= dynamic_range_min_requested) && (lp_avg_val <= dynamic_range_max_requested)) { + if (k >= DRC_INSTRUCTIONS_COUNT_MAX) return UNEXPECTED_ERROR; selected[k] = i; k++; } @@ -522,6 +528,7 @@ WORD32 impd_match_dynamic_range( deviation_min = deviation; k = 0; } + if (k >= DRC_INSTRUCTIONS_COUNT_MAX) return UNEXPECTED_ERROR; selected[k] = i; k++; } @@ -645,6 +652,7 @@ WORD32 impd_match_drc_characteristic_attempt( } } if ((ref_count > 0) && (((FLOAT32)match_count) > 0.5f * ref_count)) { + if (n >= SELECTION_CANDIDATE_COUNT_MAX) return UNEXPECTED_ERROR; memcpy(&selection_candidate_info[n], &selection_candidate_info[i], sizeof(ia_selection_candidate_info_struct)); n++; @@ -981,6 +989,7 @@ WORD32 impd_drc_set_preselection( &matching_eq_set_count, matching_eq_instrucions_index); if (err) return (err); for (j = 0; j < matching_eq_set_count; j++) { + if (n >= SELECTION_CANDIDATE_COUNT_MAX) return UNEXPECTED_ERROR; memcpy(&selection_candidate_info_step_2[n], &selection_candidate_info[k], sizeof(ia_selection_candidate_info_struct)); @@ -992,6 +1001,7 @@ WORD32 impd_drc_set_preselection( } } if (str_drc_instruction_str->requires_eq == 0) { + if (n >= SELECTION_CANDIDATE_COUNT_MAX) return UNEXPECTED_ERROR; memcpy(&selection_candidate_info_step_2[n], &selection_candidate_info[k], sizeof(ia_selection_candidate_info_struct)); @@ -999,10 +1009,9 @@ WORD32 impd_drc_set_preselection( n++; } } - for (k = 0; k < n; k++) { - memcpy(&selection_candidate_info[k], &selection_candidate_info_step_2[k], - sizeof(ia_selection_candidate_info_struct)); - } + if (n > SELECTION_CANDIDATE_COUNT_MAX) return UNEXPECTED_ERROR; + memcpy(selection_candidate_info, selection_candidate_info_step_2, + n * sizeof(ia_selection_candidate_info_struct)); *selection_candidate_count = n; n = 0; for (k = 0; k < *selection_candidate_count; k++) { @@ -1084,6 +1093,7 @@ WORD32 impd_drc_set_preselection( for (n = 0; n < pstr_loudness_info->loudness_info_album_count; n++) { if (loudness_drc_set_id_requested == pstr_loudness_info->str_loudness_info_album[n].drc_set_id) { + if (j >= SELECTION_CANDIDATE_COUNT_MAX) return UNEXPECTED_ERROR; memcpy(&selection_candidate_info[j], &selection_candidate_info[k], sizeof(ia_selection_candidate_info_struct)); j++; diff --git a/decoder/drc_src/impd_drc_static_payload.c b/decoder/drc_src/impd_drc_static_payload.c index 9639046..ca3eb2b 100644 --- a/decoder/drc_src/impd_drc_static_payload.c +++ b/decoder/drc_src/impd_drc_static_payload.c @@ -695,6 +695,8 @@ WORD32 impd_parse_loud_info_set_ext_eq( offset = loudness_info_set->loudness_info_album_count; loudness_info_set->loudness_info_album_count += loudness_info_v1_album_cnt; + if ((offset + loudness_info_v1_album_cnt) > LOUDNESS_INFO_COUNT_MAX) + return (UNEXPECTED_ERROR); for (i = 0; i < loudness_info_v1_album_cnt; i++) { err = impd_parse_loudness_info( it_bit_buff, version, @@ -703,6 +705,8 @@ WORD32 impd_parse_loud_info_set_ext_eq( } offset = loudness_info_set->loudness_info_count; loudness_info_set->loudness_info_count += loudness_info_v1_cnt; + if (offset + loudness_info_v1_cnt > LOUDNESS_INFO_COUNT_MAX) + return (UNEXPECTED_ERROR); for (i = 0; i < loudness_info_v1_cnt; i++) { err = impd_parse_loudness_info( it_bit_buff, version, &loudness_info_set->loudness_info[i + offset]); @@ -775,6 +779,7 @@ impd_parse_dwnmix_instructions( dmix_coeff = impd_read_bits_buf(it_bit_buff, 4); if (it_bit_buff->error) return it_bit_buff->error; + if (k >= DOWNMIX_COEFF_COUNT_MAX) return (UNEXPECTED_ERROR); if (ia_drc_params_struct->lfe_channel_map[j]) { dwnmix_instructions->downmix_coefficient[k] = (FLOAT32)pow(10.0f, 0.05f * dwnmix_coeff_lfe[dmix_coeff]); @@ -792,10 +797,12 @@ impd_parse_dwnmix_instructions( bs_dmix_offset = impd_read_bits_buf(it_bit_buff, 4); if (it_bit_buff->error) return it_bit_buff->error; k = 0; + for (i = 0; i < dwnmix_instructions->target_channel_count; i++) { for (j = 0; j < channel_layout->base_channel_count; j++) { dmix_coeff_v1 = impd_read_bits_buf(it_bit_buff, 5); if (it_bit_buff->error) return it_bit_buff->error; + if (k >= DOWNMIX_COEFF_COUNT_MAX) return (UNEXPECTED_ERROR); dwnmix_instructions->downmix_coefficient[k] = dwnmix_coeff_v1[dmix_coeff_v1]; k++; @@ -1152,6 +1159,9 @@ impd_parse_drc_config(ia_bit_buf_struct* it_bit_buff, drc_config->drc_coefficients_drc_count = (temp >> 6) & 7; drc_config->drc_instructions_uni_drc_count = temp & 0x3f; + if (drc_config->drc_instructions_uni_drc_count > DRC_INSTRUCTIONS_COUNT_MAX) + return (UNEXPECTED_ERROR); + err = impd_parse_ch_layout(it_bit_buff, ia_drc_params_struct, &drc_config->channel_layout); if (err) return (err); @@ -1280,6 +1290,9 @@ impd_parse_loudness_info_set( offset = loudness_info_set->loudness_info_album_count; loudness_info_set->loudness_info_album_count += loudness_info_album_count; + if ((offset + loudness_info_set->loudness_info_album_count) > + LOUDNESS_INFO_COUNT_MAX) + return (UNEXPECTED_ERROR); for (i = 0; i < loudness_info_set->loudness_info_album_count; i++) { err = impd_parse_loudness_info( it_bit_buff, version, @@ -1289,6 +1302,9 @@ impd_parse_loudness_info_set( offset = loudness_info_set->loudness_info_count; loudness_info_set->loudness_info_count += loudness_info_count; + if ((offset + loudness_info_set->loudness_info_count) > + LOUDNESS_INFO_COUNT_MAX) + return (UNEXPECTED_ERROR); for (i = 0; i < loudness_info_set->loudness_info_count; i++) { err = impd_parse_loudness_info( it_bit_buff, version, &(loudness_info_set->loudness_info[i + offset])); @@ -1500,6 +1516,8 @@ impd_parse_gain_set_params(ia_bit_buf_struct* it_bit_buff, WORD32 version, gain_set_params->band_count = impd_read_bits_buf(it_bit_buff, 4); if (it_bit_buff->error) return it_bit_buff->error; + if (gain_set_params->band_count > BAND_COUNT_MAX) return (UNEXPECTED_ERROR); + if (gain_set_params->band_count > 1) { gain_set_params->drc_band_type = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; @@ -1647,6 +1665,10 @@ impd_drc_parse_coeff( str_p_loc_drc_coefficients_uni_drc->gain_set_count = impd_read_bits_buf(it_bit_buff, 6); if (it_bit_buff->error) return it_bit_buff->error; + + if (str_p_loc_drc_coefficients_uni_drc->gain_set_count > GAIN_SET_COUNT_MAX) + return (UNEXPECTED_ERROR); + str_p_loc_drc_coefficients_uni_drc->gain_set_count_plus = str_p_loc_drc_coefficients_uni_drc->gain_set_count; for (i = 0; i < str_p_loc_drc_coefficients_uni_drc->gain_set_count; i++) { @@ -1748,6 +1770,9 @@ impd_drc_parse_coeff( str_p_loc_drc_coefficients_uni_drc->shape_num_filter = impd_read_bits_buf(it_bit_buff, 4); if (it_bit_buff->error) return it_bit_buff->error; + if (str_p_loc_drc_coefficients_uni_drc->shape_num_filter > + SHAPE_FILTER_COUNT_MAX) + return (UNEXPECTED_ERROR); for (i = 1; i <= str_p_loc_drc_coefficients_uni_drc->shape_num_filter; i++) { pstr_shape_filter_block_params = @@ -1810,8 +1835,16 @@ impd_drc_parse_coeff( str_p_loc_drc_coefficients_uni_drc->gain_sequence_count = (temp >> 6) & 0x3f; + + if (str_p_loc_drc_coefficients_uni_drc->gain_sequence_count > + SEQUENCE_COUNT_MAX) + return UNEXPECTED_ERROR; + str_p_loc_drc_coefficients_uni_drc->gain_set_count = temp & 0x3f; + if (str_p_loc_drc_coefficients_uni_drc->gain_set_count > GAIN_SET_COUNT_MAX) + return (UNEXPECTED_ERROR); + str_p_loc_drc_coefficients_uni_drc->gain_set_count_plus = str_p_loc_drc_coefficients_uni_drc->gain_set_count; for (i = 0; i < str_p_loc_drc_coefficients_uni_drc->gain_set_count; i++) { From 4692bee50b9c6ae10799cee6086d30259cb9c3e3 Mon Sep 17 00:00:00 2001 From: Ramesh Katuri Date: Thu, 18 Oct 2018 17:24:50 +0530 Subject: [PATCH 2/8] Fix for oobw-in-impd_parse_drc_instructions_uni_drc Bug:117883804 Test: vendor Change-Id: I9512dbc1d184ea838572218df3db9e91574c1460 --- decoder/drc_src/impd_drc_static_payload.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/decoder/drc_src/impd_drc_static_payload.c b/decoder/drc_src/impd_drc_static_payload.c index ca3eb2b..7e5a082 100644 --- a/decoder/drc_src/impd_drc_static_payload.c +++ b/decoder/drc_src/impd_drc_static_payload.c @@ -2131,6 +2131,7 @@ impd_parse_drc_instructions_uni_drc( ch_cnt = drc_config->channel_layout.base_channel_count; + if (ch_cnt > MAX_CHANNEL_COUNT) return (UNEXPECTED_ERROR); for (c = 0; c < MAX_CHANNEL_COUNT; c++) { unique_idx[c] = -10; unique_scaling[c] = -10.0f; @@ -2161,17 +2162,13 @@ impd_parse_drc_instructions_uni_drc( if (it_bit_buff->error) return it_bit_buff->error; repeat_parameters_cnt += 1; + if ((c + repeat_parameters_cnt) > MAX_CHANNEL_COUNT) + return (UNEXPECTED_ERROR); for (k = 0; k < repeat_parameters_cnt; k++) { str_drc_instruction_str->gain_set_index[c] = str_drc_instruction_str->gain_set_index[c - 1]; - str_drc_instruction_str->str_ducking_modifiers_for_channel[c] - .ducking_scaling_flag = - str_drc_instruction_str->str_ducking_modifiers_for_channel[c - 1] - .ducking_scaling_flag; - str_drc_instruction_str->str_ducking_modifiers_for_channel[c] - .ducking_scaling = - str_drc_instruction_str->str_ducking_modifiers_for_channel[c - 1] - .ducking_scaling; + str_drc_instruction_str->str_ducking_modifiers_for_channel[c] = + str_drc_instruction_str->str_ducking_modifiers_for_channel[c - 1]; c++; } } @@ -2283,6 +2280,7 @@ impd_parse_drc_instructions_uni_drc( ch_cnt = 1; } + if (ch_cnt > MAX_CHANNEL_COUNT) return (UNEXPECTED_ERROR); c = 0; while (c < ch_cnt) { WORD32 bs_gain_set_idx; @@ -2302,6 +2300,8 @@ impd_parse_drc_instructions_uni_drc( if (it_bit_buff->error) return it_bit_buff->error; repeat_gain_set_idx_cnt += 1; + if ((c + repeat_gain_set_idx_cnt) > MAX_CHANNEL_COUNT) + return (UNEXPECTED_ERROR); for (k = 0; k < repeat_gain_set_idx_cnt; k++) { str_drc_instruction_str->gain_set_index[c] = bs_gain_set_idx - 1; c++; From f81b8d0dbda3231ee9641def6383b8ce9ac1c082 Mon Sep 17 00:00:00 2001 From: Ramesh Katuri Date: Fri, 22 Jun 2018 15:04:25 +0530 Subject: [PATCH 3/8] Fix for Segmentation fault in ixheaacd_sbr_dec_from_mps Bug: 110629822 Test: re-run poc Change-Id: I5495b01d5d0c779185ff04eb8f1c048f353396b2 (cherry picked from commit 70396d6ced7f408c3e33df38d9266edd263e66a4) --- decoder/ixheaacd_mps_dec.c | 3 +- decoder/ixheaacd_mps_dec.h | 2 +- decoder/ixheaacd_mps_parse.c | 63 +++++++++++++++++++++----------- decoder/ixheaacd_mps_poly_filt.c | 7 ++-- decoder/ixheaacd_mps_pre_mix.c | 9 +++++ 5 files changed, 57 insertions(+), 27 deletions(-) diff --git a/decoder/ixheaacd_mps_dec.c b/decoder/ixheaacd_mps_dec.c index 851f942..3540e55 100644 --- a/decoder/ixheaacd_mps_dec.c +++ b/decoder/ixheaacd_mps_dec.c @@ -302,8 +302,9 @@ WORD32 ixheaacd_mps_apply(ia_mps_dec_state_struct* self, self->present_time_slot = 0; - ixheaacd_mps_frame_decode(self); + err = ixheaacd_mps_frame_decode(self); + if (err != 0) return err; ixheaacd_mps_qmf_hyb_analysis(self); ixheaacd_pre_and_mix_matrix_calculation(self); diff --git a/decoder/ixheaacd_mps_dec.h b/decoder/ixheaacd_mps_dec.h index 9aaa64f..527cb2e 100644 --- a/decoder/ixheaacd_mps_dec.h +++ b/decoder/ixheaacd_mps_dec.h @@ -346,7 +346,7 @@ VOID ixheaacd_mps_config(ia_mps_dec_state_struct *self, WORD32 frame_len, WORD32 residual_coding, ia_usac_dec_mps_config_struct *mps212_config); -VOID ixheaacd_mps_frame_decode(ia_mps_dec_state_struct *self); +WORD32 ixheaacd_mps_frame_decode(ia_mps_dec_state_struct *self); WORD32 ixheaacd_mps_header_decode(ia_mps_dec_state_struct *self); diff --git a/decoder/ixheaacd_mps_parse.c b/decoder/ixheaacd_mps_parse.c index 3d9bde9..a2492bd 100644 --- a/decoder/ixheaacd_mps_parse.c +++ b/decoder/ixheaacd_mps_parse.c @@ -683,7 +683,7 @@ static float ixheaacd_mps_de_quantize(int value, int param_type) { } } -static VOID ixheaacd_mps_mapindexdata( +static WORD32 ixheaacd_mps_mapindexdata( ia_mps_dec_state_struct *self, ia_mps_data_struct *frame_xxx_data, float out_data[MAX_PARAMETER_SETS_MPS][MAX_PARAMETER_BANDS], int out_idx_data[MAX_PARAMETER_SETS_MPS][MAX_PARAMETER_BANDS], @@ -790,18 +790,25 @@ static VOID ixheaacd_mps_mapindexdata( x2 = param_slots[i2]; if (interpolate_local[i] == 1) { - assert(i2 < num_parameter_sets); + if (i2 < num_parameter_sets) { + return -1; + } for (band = band_start; band < band_stop; band++) { int yi, y1, y2; + yi = 0; y1 = out_idx_data[i1][band]; y2 = out_idx_data[i2][band]; if (param_type == IPD) { if (y2 - y1 > 8) y1 += 16; if (y1 - y2 > 8) y2 += 16; - yi = (y1 + (xi - x1) * (y2 - y1) / (x2 - x1)) % 16; + if (x2 != x1) { + yi = (y1 + (xi - x1) * (y2 - y1) / (x2 - x1)) % 16; + } } else { - yi = y1 + (xi - x1) * (y2 - y1) / (x2 - x1); + if (x2 != x1) { + yi = y1 + (xi - x1) * (y2 - y1) / (x2 - x1); + } } out_idx_data[i][band] = yi; } @@ -829,26 +836,35 @@ static VOID ixheaacd_mps_mapindexdata( out_idx_data[num_parameter_sets - 1][band]; } } + + return 0; } -static VOID ixheaacd_mps_dec_and_mapframeott(ia_mps_dec_state_struct *self) { +static WORD32 ixheaacd_mps_dec_and_mapframeott(ia_mps_dec_state_struct *self) { ia_mps_bs_frame *cur_bit_stream_ptr = &(self->bs_frame); + WORD32 err_code = 0; - ixheaacd_mps_mapindexdata(self, &cur_bit_stream_ptr->cld_data, self->cld_data, - cur_bit_stream_ptr->cld_idx, - cur_bit_stream_ptr->cmp_cld_idx, - cur_bit_stream_ptr->cld_idx_pre, CLD); + err_code = ixheaacd_mps_mapindexdata( + self, &cur_bit_stream_ptr->cld_data, self->cld_data, + cur_bit_stream_ptr->cld_idx, cur_bit_stream_ptr->cmp_cld_idx, + cur_bit_stream_ptr->cld_idx_pre, CLD); + if (err_code != 0) return err_code; - ixheaacd_mps_mapindexdata(self, &cur_bit_stream_ptr->icc_data, self->icc_data, - cur_bit_stream_ptr->icc_idx, - cur_bit_stream_ptr->cmp_icc_idx, - cur_bit_stream_ptr->icc_idx_pre, ICC); + err_code = ixheaacd_mps_mapindexdata( + self, &cur_bit_stream_ptr->icc_data, self->icc_data, + cur_bit_stream_ptr->icc_idx, cur_bit_stream_ptr->cmp_icc_idx, + cur_bit_stream_ptr->icc_idx_pre, ICC); + if (err_code != 0) return err_code; + if ((self->config->bs_phase_coding)) { + err_code = ixheaacd_mps_mapindexdata( + self, &cur_bit_stream_ptr->ipd_data, self->ipd_data, + cur_bit_stream_ptr->ipd_idx, cur_bit_stream_ptr->ipd_idx_data, + cur_bit_stream_ptr->ipd_idx_prev, IPD); - if ((self->config->bs_phase_coding)) - ixheaacd_mps_mapindexdata(self, &cur_bit_stream_ptr->ipd_data, - self->ipd_data, cur_bit_stream_ptr->ipd_idx, - cur_bit_stream_ptr->ipd_idx_data, - cur_bit_stream_ptr->ipd_idx_prev, IPD); + if (err_code != 0) return err_code; + } + + return 0; } static VOID ixheaacd_mps_dec_and_mapframesmg(ia_mps_dec_state_struct *self) { @@ -939,16 +955,19 @@ static VOID ixheaacd_mps_dec_and_mapframesmg(ia_mps_dec_state_struct *self) { } } -VOID ixheaacd_mps_frame_decode(ia_mps_dec_state_struct *self) { +WORD32 ixheaacd_mps_frame_decode(ia_mps_dec_state_struct *self) { int i; - if (self->parse_nxt_frame == 1) return; + WORD32 err_code = 0; + if (self->parse_nxt_frame == 1) return 0; self->ext_frame_flag = 0; if (self->param_slots[self->num_parameter_sets - 1] != self->time_slots - 1) { self->ext_frame_flag = 1; } - ixheaacd_mps_dec_and_mapframeott(self); + err_code = ixheaacd_mps_dec_and_mapframeott(self); + + if (err_code != 0) return err_code; ixheaacd_mps_dec_and_mapframesmg(self); @@ -966,6 +985,8 @@ VOID ixheaacd_mps_frame_decode(ia_mps_dec_state_struct *self) { self->inv_param_slot_diff_Q30[i] = (int)floor(self->inv_param_slot_diff[i] * 1073741824 + 0.5); } + + return 0; } WORD32 ixheaacd_mps_header_decode(ia_mps_dec_state_struct *self) { diff --git a/decoder/ixheaacd_mps_poly_filt.c b/decoder/ixheaacd_mps_poly_filt.c index 71c930f..1d5ea47 100644 --- a/decoder/ixheaacd_mps_poly_filt.c +++ b/decoder/ixheaacd_mps_poly_filt.c @@ -73,10 +73,9 @@ VOID ixheaacd_mps_synt_pre_twiddle_dec(WORD32 *ptr_in, WORD32 *table_re, for (k = 0; k < 2 * resolution; k += 2) { tmp = ixheaacd_add32_sat(ixheaacd_mult32(ptr_in[k], table_re[k >> 1]), ixheaacd_mult32(ptr_in[k + 1], table_im[k >> 1])); - - ptr_in[k + 1] = - ixheaacd_add32_sat(ixheaacd_mult32(-ptr_in[k], table_im[k >> 1]), - ixheaacd_mult32(ptr_in[k + 1], table_re[k >> 1])); + ptr_in[k + 1] = ixheaacd_add32_sat( + ixheaacd_mult32(ixheaacd_negate32_sat(ptr_in[k]), table_im[k >> 1]), + ixheaacd_mult32(ptr_in[k + 1], table_re[k >> 1])); ptr_in[k] = tmp; } diff --git a/decoder/ixheaacd_mps_pre_mix.c b/decoder/ixheaacd_mps_pre_mix.c index 5ea8910..4aaf803 100644 --- a/decoder/ixheaacd_mps_pre_mix.c +++ b/decoder/ixheaacd_mps_pre_mix.c @@ -681,6 +681,15 @@ VOID ixheaacd_mps_phase_interpolation( r_re[ts][pb][1] = (FLOAT32)cos(t); r_im[ts][pb][1] = (FLOAT32)sin(t); ts++; + + if (ts > 71) { + ts = 0; + break; + } + if (pb > 27) { + pb = 0; + break; + } } } } From 5f84dbecff2acd6b4bfad49f55c44ea75c6470a9 Mon Sep 17 00:00:00 2001 From: Ramesh Katuri Date: Wed, 21 Nov 2018 16:56:27 +0530 Subject: [PATCH 4/8] Fix for crash due to negative size passed to memcpy In DRC, one of the memcpy is called with uninitialized variable as size, which is resulting a crash during memcpy. As a fix all the members of structure str_bit_handler are set to zero. Bug:115780779 Test: vendor Change-Id: Ib991f7ca6fde9d448b975b4a9fa34234fa54231e --- decoder/drc_src/impd_drc_init.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/decoder/drc_src/impd_drc_init.c b/decoder/drc_src/impd_drc_init.c index 5f51a3f..cd6d467 100644 --- a/decoder/drc_src/impd_drc_init.c +++ b/decoder/drc_src/impd_drc_init.c @@ -19,6 +19,7 @@ */ #include #include +#include #include "impd_type_def.h" #include "impd_error_standards.h" @@ -111,19 +112,7 @@ IA_ERRORCODE impd_drc_set_default_config(ia_drc_api_struct *p_obj_drc) { p_obj_drc->str_config.effect_type = 0; p_obj_drc->str_config.target_loudness = -24; p_obj_drc->str_config.loud_norm_flag = 0; - p_obj_drc->str_bit_handler.byte_index_bs = 0; - p_obj_drc->str_bit_handler.num_bytes_bs = 0; - p_obj_drc->str_bit_handler.num_bits_offset_bs = 0; - p_obj_drc->str_bit_handler.num_bits_read_bs = 0; - p_obj_drc->str_bit_handler.cpy_over = 0; - p_obj_drc->str_bit_handler.num_bytes_bs_drc_config = 0; - p_obj_drc->str_bit_handler.cpy_over_ic = 0; - p_obj_drc->str_bit_handler.num_bytes_bs_loudness_info = 0; - p_obj_drc->str_bit_handler.cpy_over_il = 0; - p_obj_drc->str_bit_handler.num_bytes_bs_unidrc_interface = 0; - p_obj_drc->str_bit_handler.num_bits_read_bs_unidrc_interface = 0; - p_obj_drc->str_bit_handler.cpy_over_in = 0; - p_obj_drc->str_bit_handler.gain_stream_flag = 0; + memset(&p_obj_drc->str_bit_handler, 0, sizeof(p_obj_drc->str_bit_handler)); return IA_NO_ERROR; } From b0c549e5d8b348697cd25a3135cf7c95b98717e3 Mon Sep 17 00:00:00 2001 From: Ramesh Katuri Date: Wed, 31 Oct 2018 15:50:27 +0530 Subject: [PATCH 5/8] Fix for crash in ixheaacd_esbr_synthesis_regrp Inside ia_sbr_frame_info_data_struct, limit table is defined as WORD32 lim_table[4][12 + 1]; lim_table is accessed using gate_mode which is defined as WORD32 gate_mode[4]; For all these below issues one of the value of gate_mode is greater than 12, when lim_table is accessed with more than 12 we are getting some garbage value which is causing pointer corruption for b/118386824, Heap buffer overflow for b/118389774 and stack buffer overflow for b/118494588. As a fix we are returning fatal error if value in gate_mode > 12 Bug:118386824 Bug:118389774 Bug:118494588 Test: vendor Change-Id: I713c5438f56a13f06f0f76ed22ad96ff667741a4 --- decoder/ixheaacd_env_extr.h | 13 ++++++------ decoder/ixheaacd_esbr_envcal.c | 36 ++++++++++++++++++---------------- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/decoder/ixheaacd_env_extr.h b/decoder/ixheaacd_env_extr.h index 5078d98..109dfe2 100644 --- a/decoder/ixheaacd_env_extr.h +++ b/decoder/ixheaacd_env_extr.h @@ -19,7 +19,7 @@ */ #ifndef IXHEAACD_ENV_EXTR_H #define IXHEAACD_ENV_EXTR_H - +#include "ixheaacd_error_standards.h" #define ENV_EXP_FRACT 0 #define EXP_BITS 6 @@ -170,12 +170,11 @@ VOID ixheaacd_huffman_decode(WORD32 it_bit_buff, WORD16 *h_index, WORD16 *len, const UWORD16 *input_table, const UWORD32 *idx_table); -VOID ixheaacd_createlimiterbands(WORD32 lim_table[4][12 + 1], - WORD32 gate_mode[4], WORD16 *freq_band_tbl, - WORD32 ixheaacd_num_bands, - WORD32 x_over_qmf[MAX_NUM_PATCHES], - WORD32 b_patching_mode, WORD32 upsamp_4_flag, - struct ixheaacd_lpp_trans_patch *patch_param); +IA_ERRORCODE ixheaacd_createlimiterbands( + WORD32 lim_table[4][12 + 1], WORD32 gate_mode[4], WORD16 *freq_band_tbl, + WORD32 ixheaacd_num_bands, WORD32 x_over_qmf[MAX_NUM_PATCHES], + WORD32 b_patching_mode, WORD32 upsamp_4_flag, + struct ixheaacd_lpp_trans_patch *patch_param); VOID ixheaacd_apply_inter_tes(FLOAT32 *qmf_real1, FLOAT32 *qmf_imag1, FLOAT32 *qmf_real, FLOAT32 *qmf_imag, diff --git a/decoder/ixheaacd_esbr_envcal.c b/decoder/ixheaacd_esbr_envcal.c index b90df22..e1bb1c7 100644 --- a/decoder/ixheaacd_esbr_envcal.c +++ b/decoder/ixheaacd_esbr_envcal.c @@ -167,19 +167,21 @@ WORD32 ixheaacd_sbr_env_calc(ia_sbr_frame_info_data_struct *frame_data, esbr_start_up = 1; esbr_start_up_pvc = 1; phase_index = 0; - ixheaacd_createlimiterbands( - (*lim_table), (*gate_mode), - frame_data->pstr_sbr_header->pstr_freq_band_data->freq_band_tbl_lo, - num_sf_bands[LOW], x_over_qmf, frame_data->sbr_patching_mode, - upsamp_4_flag, &frame_data->patch_param); + if (ixheaacd_createlimiterbands( + (*lim_table), (*gate_mode), + frame_data->pstr_sbr_header->pstr_freq_band_data->freq_band_tbl_lo, + num_sf_bands[LOW], x_over_qmf, frame_data->sbr_patching_mode, + upsamp_4_flag, &frame_data->patch_param)) + return IA_FATAL_ERROR; } if (frame_data->sbr_patching_mode != frame_data->prev_sbr_patching_mode) { - ixheaacd_createlimiterbands( - (*lim_table), (*gate_mode), - frame_data->pstr_sbr_header->pstr_freq_band_data->freq_band_tbl_lo, - num_sf_bands[LOW], x_over_qmf, frame_data->sbr_patching_mode, - upsamp_4_flag, &frame_data->patch_param); + if (ixheaacd_createlimiterbands( + (*lim_table), (*gate_mode), + frame_data->pstr_sbr_header->pstr_freq_band_data->freq_band_tbl_lo, + num_sf_bands[LOW], x_over_qmf, frame_data->sbr_patching_mode, + upsamp_4_flag, &frame_data->patch_param)) + return IA_FATAL_ERROR; frame_data->prev_sbr_patching_mode = frame_data->sbr_patching_mode; } @@ -789,12 +791,11 @@ WORD32 ixheaacd_sbr_env_calc(ia_sbr_frame_info_data_struct *frame_data, return 0; } -VOID ixheaacd_createlimiterbands(WORD32 lim_table[4][12 + 1], - WORD32 gate_mode[4], WORD16 *freq_band_tbl, - WORD32 ixheaacd_num_bands, - WORD32 x_over_qmf[MAX_NUM_PATCHES], - WORD32 b_patching_mode, WORD32 upsamp_4_flag, - struct ixheaacd_lpp_trans_patch *patch_param) { +IA_ERRORCODE ixheaacd_createlimiterbands( + WORD32 lim_table[4][12 + 1], WORD32 gate_mode[4], WORD16 *freq_band_tbl, + WORD32 ixheaacd_num_bands, WORD32 x_over_qmf[MAX_NUM_PATCHES], + WORD32 b_patching_mode, WORD32 upsamp_4_flag, + struct ixheaacd_lpp_trans_patch *patch_param) { WORD32 i, j, k, is_patch_border[2]; WORD32 patch_borders[MAX_NUM_PATCHES + 1]; WORD32 temp_limiter_band_calc[32 + MAX_NUM_PATCHES + 1]; @@ -887,11 +888,12 @@ VOID ixheaacd_createlimiterbands(WORD32 lim_table[4][12 + 1], } } } - + if (gate_mode[i] > 12) return IA_FATAL_ERROR; for (k = 0; k <= gate_mode[i]; k++) { lim_table[i][k] = temp_limiter_band_calc[k]; } } + return IA_NO_ERROR; } VOID ixheaacd_apply_inter_tes(FLOAT32 *qmf_real1, FLOAT32 *qmf_imag1, From 2e513342a16db22998a52085b8c3b0b01a462f02 Mon Sep 17 00:00:00 2001 From: Ramesh Katuri Date: Tue, 30 Oct 2018 14:35:04 +0530 Subject: [PATCH 6/8] Fix for stack buffer overflow in ixheaacd_latm_stream_mux_config Bug:118149009 Test: vendor Change-Id: I16213a2db36e9d678f7105edda9a4a6c17a3f8a6 --- decoder/ixheaacd_headerdecode.c | 9 ++++++--- decoder/ixheaacd_latmdemux.c | 20 ++++++++++---------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/decoder/ixheaacd_headerdecode.c b/decoder/ixheaacd_headerdecode.c index c28833e..140ad78 100644 --- a/decoder/ixheaacd_headerdecode.c +++ b/decoder/ixheaacd_headerdecode.c @@ -81,6 +81,8 @@ #include "ixheaacd_struct.h" #include "ixheaacd_function_selector.h" +#include "ixheaacd_error_standards.h" + #undef ALLOW_SMALL_FRAMELENGTH #define ALLOW_SMALL_FRAMELENGTH @@ -811,11 +813,12 @@ WORD32 ixheaacd_check_if_adts(ia_adts_header_struct *adts, (adts->profile != AAC_LC_PROFILE)); } -WORD32 ixheaacd_latm_header_decode( +IA_ERRORCODE ixheaacd_latm_header_decode( ia_aac_dec_state_struct *aac_state_struct, struct ia_bit_buf_struct *it_bit_buff, WORD32 *bytes_consumed, ia_sampling_rate_info_struct *pstr_samp_rate_info) { - WORD32 sync, result; + WORD32 sync; + IA_ERRORCODE result; WORD32 next_sync, audio_mux_len_bytes_last; WORD32 audio_mux_len_bits_last; WORD32 sync_status = aac_state_struct->sync_status; @@ -931,7 +934,7 @@ WORD32 ixheaacd_latm_header_decode( } } } - return 0; + return IA_NO_ERROR; } WORD32 ixheaacd_aac_headerdecode( diff --git a/decoder/ixheaacd_latmdemux.c b/decoder/ixheaacd_latmdemux.c index d800c88..fb216f0 100644 --- a/decoder/ixheaacd_latmdemux.c +++ b/decoder/ixheaacd_latmdemux.c @@ -80,6 +80,7 @@ #include "ixheaacd_multichannel.h" #include "ixheaacd_headerdecode.h" +#include "ixheaacd_error_standards.h" WORD32 ixheaacd_latm_au_chunk_length_info( struct ia_bit_buf_struct *it_bit_buff) { @@ -150,7 +151,7 @@ static UWORD32 ixheaacd_latm_get_value(ia_bit_buf_struct *it_bit_buff) { ixheaacd_read_bits_buf(it_bit_buff, 8); } -WORD32 ixheaacd_latm_stream_mux_config( +IA_ERRORCODE ixheaacd_latm_stream_mux_config( struct ia_bit_buf_struct *it_bit_buff, ixheaacd_latm_struct *latm_element, ia_aac_dec_state_struct *aac_state_struct, ia_sampling_rate_info_struct *sample_rate_info) { @@ -159,7 +160,7 @@ WORD32 ixheaacd_latm_stream_mux_config( WORD32 bytes_consumed; WORD32 audio_mux_version_a; UWORD32 tara_buf_fullness; - WORD32 error_code = AAC_DEC_OK; + IA_ERRORCODE error_code = AAC_DEC_OK; ixheaacd_latm_layer_info *layer_info = 0; latm_element->audio_mux_version = ixheaacd_read_bits_buf(it_bit_buff, 1); @@ -178,13 +179,13 @@ WORD32 ixheaacd_latm_stream_mux_config( latm_element->num_sub_frames = ixheaacd_read_bits_buf(it_bit_buff, 6) + 1; - if (latm_element->num_sub_frames != 1) { - error_code = IA_ENHAACPLUS_DEC_EXE_FATAL_INVALID_LOAS_HEADER; - return error_code; - } + if (latm_element->num_sub_frames != 1) + return IA_ENHAACPLUS_DEC_EXE_FATAL_INVALID_LOAS_HEADER; latm_element->num_program = ixheaacd_read_bits_buf(it_bit_buff, 4) + 1; + if (latm_element->num_program > LATM_MAX_PROG) return IA_FATAL_ERROR; + for (prog = 0; prog < latm_element->num_program; prog++) { latm_element->num_layer = ixheaacd_read_bits_buf(it_bit_buff, 3) + 1; @@ -250,8 +251,7 @@ WORD32 ixheaacd_latm_stream_mux_config( break; default: - error_code = IA_ENHAACPLUS_DEC_EXE_FATAL_INVALID_LOAS_HEADER; - return error_code; + return IA_ENHAACPLUS_DEC_EXE_FATAL_INVALID_LOAS_HEADER; } } } @@ -284,12 +284,12 @@ WORD32 ixheaacd_latm_stream_mux_config( return (error_code); } -WORD32 ixheaacd_latm_audio_mux_element( +IA_ERRORCODE ixheaacd_latm_audio_mux_element( struct ia_bit_buf_struct *it_bit_buff, ixheaacd_latm_struct *latm_element, ia_aac_dec_state_struct *aac_state_struct, ia_sampling_rate_info_struct *sample_rate_info) { UWORD32 i; - WORD32 error_code = AAC_DEC_OK; + IA_ERRORCODE error_code = AAC_DEC_OK; ixheaacd_read_bits_buf(it_bit_buff, 13); From 56a2e1e9c6a7e66777d060d424413580e0d85c67 Mon Sep 17 00:00:00 2001 From: Ramesh Katuri Date: Wed, 31 Oct 2018 16:10:53 +0530 Subject: [PATCH 7/8] Fix for oobw in impd_dec_slopes in DRC dynamic payload Bug:118143575 Test: vendor Change-Id: I35940099dc804a96a5790bf8e8b29df049838a17 --- decoder/drc_src/impd_drc_dynamic_payload.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/decoder/drc_src/impd_drc_dynamic_payload.c b/decoder/drc_src/impd_drc_dynamic_payload.c index 6bc1be7..f93f49e 100644 --- a/decoder/drc_src/impd_drc_dynamic_payload.c +++ b/decoder/drc_src/impd_drc_dynamic_payload.c @@ -123,7 +123,7 @@ WORD32 impd_dec_gains(ia_bit_buf_struct* it_bit_buff, WORD32 no_nodes, WORD32 impd_dec_slopes(ia_bit_buf_struct* it_bit_buff, WORD32* no_nodes, WORD32 gain_interpolation_type, ia_node_struct* str_node) { - WORD32 k, e, m, bit; + WORD32 k, e, bit; WORD32 code; WORD32 code_found; FLOAT32 slope_value = 0; @@ -141,6 +141,7 @@ WORD32 impd_dec_slopes(ia_bit_buf_struct* it_bit_buff, WORD32* no_nodes, end_marker = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; } + if (k > NODE_COUNT_MAX) return UNEXPECTED_ERROR; *no_nodes = k; if (gain_interpolation_type == GAIN_INTERPOLATION_TYPE_SPLINE) { @@ -150,7 +151,7 @@ WORD32 impd_dec_slopes(ia_bit_buf_struct* it_bit_buff, WORD32* no_nodes, code_found = 0; e = 0; while ((e < no_slope_code_entries) && (!code_found)) { - for (m = 0; m < ptr_slope_code_table[e].size - num_bits_read; m++) { + while (num_bits_read < ptr_slope_code_table[e].size) { bit = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; code = (code << 1) + bit; @@ -163,6 +164,7 @@ WORD32 impd_dec_slopes(ia_bit_buf_struct* it_bit_buff, WORD32* no_nodes, break; } e++; + if (e >= no_slope_code_entries) return UNEXPECTED_ERROR; } } str_node[k].slope = slope_value; From ed831abc6524db9855e4f55454d0fcdf13e9d0ce Mon Sep 17 00:00:00 2001 From: Ramesh Katuri Date: Sat, 17 Nov 2018 14:52:48 +0530 Subject: [PATCH 8/8] Fix for oobw in impd_parse_drc_instructions_uni_drc() gain_set_index_for_channel_group[] is any array of size CHANNEL_GROUP_COUNT_MAX i.e 24. This array is accessed using str_drc_instruction_str->num_drc_ch_groups as index, whose value can be more than 24. Bound check is added for str_drc_instruction_str->num_drc_ch_groups before accessing gain_set_index_for_channel_group[] Bug:117832864 Test: vendor Change-Id: I3799c2de6926f1193a5e0193bc3b5863c478d4ab --- decoder/drc_src/impd_drc_static_payload.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/decoder/drc_src/impd_drc_static_payload.c b/decoder/drc_src/impd_drc_static_payload.c index 7e5a082..871a452 100644 --- a/decoder/drc_src/impd_drc_static_payload.c +++ b/decoder/drc_src/impd_drc_static_payload.c @@ -2239,6 +2239,9 @@ impd_parse_drc_instructions_uni_drc( str_drc_instruction_str->num_drc_ch_groups = g; } + if (str_drc_instruction_str->num_drc_ch_groups > + min(CHANNEL_GROUP_COUNT_MAX, MAX_CHANNEL_COUNT)) + return UNEXPECTED_ERROR; for (g = 0; g < str_drc_instruction_str->num_drc_ch_groups; g++) { WORD32 set = (str_drc_instruction_str->drc_set_effect & EFFECT_BIT_DUCK_OTHER) @@ -2344,6 +2347,10 @@ impd_parse_drc_instructions_uni_drc( } str_drc_instruction_str->num_drc_ch_groups = g; + + if (str_drc_instruction_str->num_drc_ch_groups > + min(CHANNEL_GROUP_COUNT_MAX, MAX_CHANNEL_COUNT)) + return UNEXPECTED_ERROR; for (g = 0; g < str_drc_instruction_str->num_drc_ch_groups; g++) { WORD32 set, band_count;