Fix for the Index-out-of-bounds in iusace_quantize_lines

These changes handle the index-out-of-bounds runtime error
reported when the bit consumption exceeds the bit reservoir
and global gain reaches the maximum value. The issue is
reported with USAC and the same changes are extended to AAC.

Bug: ossFuzz: 63019
Test: poc in bug
This commit is contained in:
Akshay Ragir 2023-10-12 12:41:06 +05:30 committed by Divya B M
parent 87abf1f1b0
commit e8d026548e
15 changed files with 67 additions and 28 deletions

View file

@ -940,7 +940,7 @@ IA_ERRORCODE ixheaace_usac_encode(FLOAT32 **ptr_input,
ixheaace_audio_specific_config_struct *pstr_asc,
ia_bit_buf_struct *pstr_it_bit_buff,
ixheaace_pstr_sbr_enc ptr_env_encoder, FLOAT32 **pp_drc_inp,
WORD32 *is_quant_spec_zero) {
WORD32 *is_quant_spec_zero, WORD32 *is_gain_limited) {
IA_ERRORCODE err = IA_NO_ERROR;
WORD32 i_ch, i, k;
ia_usac_data_struct *ptr_usac_data = pstr_state;
@ -1293,7 +1293,7 @@ IA_ERRORCODE ixheaace_usac_encode(FLOAT32 **ptr_input,
: ((ptr_usac_data->core_mode[ch_offset] == CORE_MODE_FD))) {
err = iusace_fd_encode(pstr_sfb_prms, usac_independency_flg, ptr_usac_data, ptr_usac_config,
pstr_it_bit_buff, nr_core_coder_channels, ch_offset, elem_idx,
&bits_written, is_quant_spec_zero);
&bits_written, is_quant_spec_zero, is_gain_limited);
if (err) {
return err;

View file

@ -24,4 +24,4 @@ IA_ERRORCODE iusace_fd_encode(ia_sfb_params_struct *pstr_sfb_prms, WORD32 usac_i
ia_usac_encoder_config_struct *pstr_usac_config,
ia_bit_buf_struct *pstr_it_bit_buff, WORD32 nr_core_coder_ch,
WORD32 chn, WORD32 ele_id, WORD32 *bit_written,
WORD32 *is_quant_spec_zero);
WORD32 *is_quant_spec_zero, WORD32* is_gain_limited);

View file

@ -111,7 +111,8 @@ IA_ERRORCODE iusace_quantize_spec(ia_sfb_params_struct *pstr_sfb_prms,
WORD32 usac_independancy_flag, WORD32 num_chans,
ia_usac_data_struct *ptr_usac_data,
ia_usac_encoder_config_struct *ptr_usac_config, WORD32 chn,
WORD32 ele_id, WORD32 *is_quant_spec_zero);
WORD32 ele_id, WORD32 *is_quant_spec_zero,
WORD32 *is_gain_limited);
IA_ERRORCODE iusace_grouping(ia_sfb_params_struct *pstr_sfb_prms, WORD32 num_chans,
ia_usac_data_struct *ptr_usac_data,

View file

@ -118,4 +118,5 @@ typedef struct {
#define MIN_NUM_CORE_CODER_CHANNELS (1)
/*-------------------------- defines --------------------------------------*/
#define BUFFERSIZE 1024 /* anc data */
#define BUFFERSIZE 1024 /* anc data */
#define MAX_GAIN_INDEX (128)

View file

@ -2726,7 +2726,8 @@ static IA_ERRORCODE ia_enhaacplus_enc_execute(ixheaace_api_struct *pstr_api_stru
&(pstr_api_struct->pstr_state->bit_stream), flag_last_element,
write_program_config_element, i_num_coup_channels, i_channels_mask, ele_idx,
total_fill_bits, total_channels, aot, pstr_api_struct->config->adts_flag,
num_bs_elements, &pstr_api_struct->pstr_state->is_quant_spec_zero);
num_bs_elements, &pstr_api_struct->pstr_state->is_quant_spec_zero,
&pstr_api_struct->pstr_state->is_gain_limited);
if (error != IA_NO_ERROR) {
return error;
}
@ -3273,7 +3274,8 @@ static IA_ERRORCODE iusace_process(ixheaace_api_struct *pstr_api_struct) {
&pstr_api_struct->pstr_state->str_usac_enc_data,
&pstr_api_struct->pstr_state->audio_specific_config, pstr_it_bit_buff,
pstr_sbr_encoder, pstr_api_struct->pstr_state->pp_drc_in_buf,
&pstr_api_struct->pstr_state->is_quant_spec_zero);
&pstr_api_struct->pstr_state->is_quant_spec_zero,
&pstr_api_struct->pstr_state->is_gain_limited);
if (error) return error;
padding_bits = 8 - (pstr_it_bit_buff->cnt_bits & 7);
@ -3610,6 +3612,7 @@ IA_ERRORCODE ixheaace_process(pVOID pstr_obj_ixheaace, pVOID pv_input, pVOID pv_
ixheaace_api_struct *pstr_api_struct = (ixheaace_api_struct *)pstr_obj_ixheaace;
ixheaace_output_config *pstr_output_config = (ixheaace_output_config *)pv_output;
pstr_api_struct->pstr_state->is_quant_spec_zero = 0;
pstr_api_struct->pstr_state->is_gain_limited = 0;
if (!pstr_api_struct->usac_en) {
for (ele_idx = 0; ele_idx < pstr_api_struct->config[0].num_bs_elements; ele_idx++) {
error = ia_enhaacplus_enc_execute(pstr_api_struct, ele_idx);
@ -3617,11 +3620,17 @@ IA_ERRORCODE ixheaace_process(pVOID pstr_obj_ixheaace, pVOID pv_input, pVOID pv_
if ((error == IA_NO_ERROR) && (pstr_api_struct->pstr_state->is_quant_spec_zero)) {
error = IA_EXHEAACE_EXE_NONFATAL_QUANTIZATION_SPECTRUM_ZERO;
}
if ((error == IA_NO_ERROR) && (pstr_api_struct->pstr_state->is_gain_limited)) {
error = IA_EXHEAACE_EXE_NONFATAL_QUANTIZATION_INSUFFICIENT_BITRES;
}
} else {
error = iusace_process(pstr_api_struct);
if ((error == IA_NO_ERROR) && (pstr_api_struct->pstr_state->is_quant_spec_zero)) {
error = IA_EXHEAACE_EXE_NONFATAL_USAC_QUANTIZATION_SPECTRUM_ZERO;
}
if ((error == IA_NO_ERROR) && (pstr_api_struct->pstr_state->is_gain_limited)) {
error = IA_EXHEAACE_EXE_NONFATAL_USAC_QUANTIZATION_INSUFFICIENT_BITRES;
}
}
pstr_output_config->i_out_bytes = pstr_api_struct->pstr_state->i_out_bytes;
return error;

View file

@ -44,4 +44,4 @@ IA_ERRORCODE ixheaace_usac_encode(FLOAT32 **ptr_input,
ixheaace_audio_specific_config_struct *pstr_asc,
ia_bit_buf_struct *pstr_it_bit_buff,
ixheaace_pstr_sbr_enc ptr_env_encoder, FLOAT32 **ptr_drc_inp,
WORD32 *is_quant_spec_zero);
WORD32 *is_quant_spec_zero, WORD32 *is_gain_restricted);

View file

@ -66,7 +66,7 @@ IA_ERRORCODE ia_enhaacplus_enc_aac_core_encode(
VOID *ptr_bit_stream, FLAG flag_last_element, WORD32 *write_program_config_element,
WORD32 i_num_coup_channels, WORD32 i_channels_mask, WORD32 ele_idx, WORD32 *total_fill_bits,
WORD32 total_channels, WORD32 aot, WORD32 adts_flag, WORD32 num_bs_elements,
WORD32 *is_quant_spec_zero) {
WORD32 *is_quant_spec_zero, WORD32 *is_gain_limited) {
IA_ERRORCODE err_code = IA_NO_ERROR;
iexheaac_encoder_str *pstr_aac_encoder = pstr_aac_enc[ele_idx];
ixheaace_element_info *pstr_element_info = &pstr_aac_encoder->element_info;
@ -174,7 +174,8 @@ IA_ERRORCODE ia_enhaacplus_enc_aac_core_encode(
pstr_aac_encoder->qc_out.qc_channel[pstr_element_info->channel_index[0]],
&pstr_aac_encoder->qc_out.qc_element, MIN(anc_data_bytes_left, anc_data_bytes),
pstr_aac_tabs, adts_flag, aot, stat_bits_flag, flag_last_element, frame_len_long,
pstr_aac_encoder->pstr_aac_scratch->shared_buffer5, is_quant_spec_zero);
pstr_aac_encoder->pstr_aac_scratch->shared_buffer5, is_quant_spec_zero,
is_gain_limited);
if (err_code != IA_NO_ERROR) {
return err_code;

View file

@ -109,7 +109,7 @@ IA_ERRORCODE ia_enhaacplus_enc_aac_core_encode(
VOID *ptr_bit_stream, FLAG flag_last_element, WORD32 *write_program_config_element,
WORD32 i_num_coup_channels, WORD32 i_channels_mask, WORD32 ele_idx, WORD32 *total_fill_bits,
WORD32 total_channels, WORD32 aot, WORD32 adts_flag, WORD32 num_bs_elements,
WORD32 *is_quant_spec_zero);
WORD32 *is_quant_spec_zero, WORD32 *is_gain_limited);
VOID ia_enhaacplus_enc_set_shared_bufs(iaace_scratch *scr, WORD32 **shared_buf1,
WORD32 **shared_buf2, WORD32 **shared_buf3,

View file

@ -142,12 +142,14 @@ typedef enum {
// AAC Profiles
IA_EXHEAACE_EXE_NONFATAL_QUANTIZATION_SPECTRUM_ZERO = 0x00001800,
IA_EXHEAACE_EXE_NONFATAL_QUANTIZATION_INSUFFICIENT_BITRES,
// MPS
IA_EXHEAACE_EXE_NONFATAL_MPS_ENCODE_ERROR = 0x00001900,
IA_EXHEAACE_EXE_NONFATAL_MPS_INVALID_DATA_BANDS,
// USAC
IA_EXHEAACE_EXE_NONFATAL_USAC_QUANTIZATION_SPECTRUM_ZERO = 0x00001A00,
IA_EXHEAACE_EXE_NONFATAL_USAC_QUANTIZATION_INSUFFICIENT_BITRES,
// DRC
// ESBR

View file

@ -57,7 +57,7 @@ IA_ERRORCODE iusace_fd_encode(ia_sfb_params_struct *pstr_sfb_prms, WORD32 usac_i
ia_usac_encoder_config_struct *pstr_usac_config,
ia_bit_buf_struct *pstr_it_bit_buff, WORD32 nr_core_coder_ch,
WORD32 chn, WORD32 ele_id, WORD32 *bit_written,
WORD32 *is_quant_spec_zero) {
WORD32 *is_quant_spec_zero, WORD32 *is_gain_limited) {
iusace_scratch_mem *pstr_scratch = &pstr_usac_data->str_scratch;
IA_ERRORCODE err_code = 0;
WORD32 i_ch, idx = 0;
@ -96,7 +96,7 @@ IA_ERRORCODE iusace_fd_encode(ia_sfb_params_struct *pstr_sfb_prms, WORD32 usac_i
err_code = iusace_quantize_spec(pstr_sfb_prms, usac_independancy_flag, nr_core_coder_ch,
pstr_usac_data, pstr_usac_config, chn, ele_id,
is_quant_spec_zero);
is_quant_spec_zero, is_gain_limited);
if (err_code) return err_code;
for (i_ch = chn; i_ch < chn + nr_core_coder_ch; i_ch++) {

View file

@ -56,6 +56,7 @@
#include "iusace_block_switch_const.h"
#include "iusace_rom.h"
#include "ixheaace_cplx_pred.h"
#include "ixheaace_aac_constants.h"
static WORD32 iusace_window_shape[5] = {WIN_SEL_1, WIN_SEL_0, WIN_SEL_0, WIN_SEL_1, WIN_SEL_0};
@ -444,7 +445,8 @@ IA_ERRORCODE iusace_quantize_spec(ia_sfb_params_struct *pstr_sfb_prms,
WORD32 usac_independancy_flag, WORD32 num_chans,
ia_usac_data_struct *ptr_usac_data,
ia_usac_encoder_config_struct *ptr_usac_config, WORD32 chn,
WORD32 ele_id, WORD32 *is_quant_spec_zero) {
WORD32 ele_id, WORD32 *is_quant_spec_zero,
WORD32 *is_gain_limited) {
IA_ERRORCODE err_code;
WORD32 i = 0, sfb;
WORD32 j = 0;
@ -473,6 +475,7 @@ IA_ERRORCODE iusace_quantize_spec(ia_sfb_params_struct *pstr_sfb_prms,
WORD32 *ptr_num_sfb = pstr_sfb_prms->num_sfb;
WORD32 *ptr_num_window_groups = pstr_sfb_prms->num_window_groups;
WORD32 bitres_bits, bitres_diff;
WORD32 gain;
memset(num_scfs, 0, 2 * sizeof(num_scfs[0]));
@ -531,7 +534,7 @@ IA_ERRORCODE iusace_quantize_spec(ia_sfb_params_struct *pstr_sfb_prms,
idx = 0;
for (ch = chn; ch < chn + num_chans; ch++) {
iterations = 0;
gain = 0;
for (kk = 0; kk < ptr_usac_config->ccfl; kk++) {
ptr_exp_spec[kk] = (FLOAT32)pstr_psy_out[ch].ptr_spec_coeffs[kk];
ptr_mdct_spec_float[kk] = (FLOAT32)pstr_psy_out[ch].ptr_spec_coeffs[kk];
@ -544,6 +547,7 @@ IA_ERRORCODE iusace_quantize_spec(ia_sfb_params_struct *pstr_sfb_prms,
sfb_offs += pstr_psy_out[ch].sfb_per_group) {
for (sfb = 0; sfb < pstr_psy_out[ch].max_sfb_per_grp; sfb++) {
WORD32 scalefactor = pstr_qc_out->str_qc_out_chan[idx].scalefactor[sfb + sfb_offs];
gain = MAX(gain, pstr_qc_out->str_qc_out_chan[idx].global_gain - scalefactor);
iusace_quantize_lines(
pstr_qc_out->str_qc_out_chan[idx].global_gain - scalefactor,
pstr_psy_out[ch].sfb_offsets[sfb_offs + sfb + 1] -
@ -600,18 +604,26 @@ IA_ERRORCODE iusace_quantize_spec(ia_sfb_params_struct *pstr_sfb_prms,
if (max_bits > max_ch_dyn_bits[idx]) {
constraints_fulfilled = 0;
}
if (!constraints_fulfilled) {
pstr_qc_out->str_qc_out_chan[idx].global_gain++;
}
if (quant_spec_is_zero == 1) {
constraints_fulfilled = 1;
/*Bit consuption is exceding bit reserviour, there is no scope left for bit consumption
/*Bit consuption is exceding bit reservoir, there is no scope left for bit consumption
reduction, as spectrum is zero. Hence breaking the quantization loop. */
if (iterations > 0) {
*is_quant_spec_zero = 1;
max_bits = max_ch_dyn_bits[idx];
}
}
if ((gain == MAX_GAIN_INDEX) && (constraints_fulfilled == 0)) {
/* Bit consuption is exceding bit reservoir, there is no scope left for bit consumption
reduction, as gain has reached the maximum value. Hence breaking the quantization
loop. */
constraints_fulfilled = 1;
*is_gain_limited = 1;
max_bits = max_ch_dyn_bits[idx];
}
if (!constraints_fulfilled) {
pstr_qc_out->str_qc_out_chan[idx].global_gain++;
}
iterations++;
} while (!constraints_fulfilled);

View file

@ -75,7 +75,7 @@ IA_ERRORCODE ia_enhaacplus_enc_qc_main(
ixheaace_qc_out_element *pstr_qc_out_element, WORD32 ancillary_data_bytes,
ixheaace_aac_tables *pstr_aac_tables, WORD32 adts_flag, WORD32 aot, WORD32 stat_bits_flag,
WORD32 flag_last_element, WORD32 frame_len_long, WORD8 *ptr_scratch,
WORD32 *is_quant_spec_zero) {
WORD32 *is_quant_spec_zero, WORD32 *is_gain_limited) {
IA_ERRORCODE err_code;
WORD32 ch;
WORD32 i = 0;
@ -90,6 +90,7 @@ IA_ERRORCODE ia_enhaacplus_enc_qc_main(
ptr_scratch += sizeof(ixheaace_qc_stack);
ia_adj_thr_elem_struct *pstr_adj_thr_elem = &pstr_qc_state->str_adj_thr.str_adj_thr_ele;
WORD32 gain;
if (pstr_el_bits->bit_res_level < 0) {
return IA_EXHEAACE_EXE_FATAL_INVALID_BIT_RES_LEVEL;
@ -143,6 +144,7 @@ IA_ERRORCODE ia_enhaacplus_enc_qc_main(
are fulfilled */
WORD32 spec_idx, sfb_offs, sfb;
iterations = 0;
gain = 0;
for (spec_idx = 0; spec_idx < frame_len_long; spec_idx++) {
ptr_stack->exp_spec[spec_idx] = (FLOAT32)psy_out_ch[ch].ptr_spec_coeffs[spec_idx];
ptr_stack->mdct_spec_float[spec_idx] = (FLOAT32)psy_out_ch[ch].ptr_spec_coeffs[spec_idx];
@ -156,6 +158,7 @@ IA_ERRORCODE ia_enhaacplus_enc_qc_main(
sfb_offs += psy_out_ch[ch].sfb_per_group) {
for (sfb = 0; sfb < psy_out_ch[ch].max_sfb_per_grp; sfb++) {
WORD32 scalefactor = pstr_qc_out_ch[ch].scalefactor[sfb + sfb_offs];
gain = MAX(gain, pstr_qc_out_ch[ch].global_gain - scalefactor);
iaace_quantize_lines(
pstr_qc_out_ch[ch].global_gain - scalefactor,
psy_out_ch[ch].sfb_offsets[sfb_offs + sfb + 1] -
@ -204,19 +207,26 @@ IA_ERRORCODE ia_enhaacplus_enc_qc_main(
constraints_fulfilled = 0;
}
if (!constraints_fulfilled) {
pstr_qc_out_ch[ch].global_gain++;
}
if (quant_spec_is_zero == 1) {
constraints_fulfilled = 1;
/*Bit consuption is exceding bit reserviour, there is no scope left for bit consumption
/*Bit consuption is exceding bit reservoir, there is no scope left for bit consumption
reduction, as spectrum is zero. Hence breaking the quantization loop. */
if (iterations > 0) {
*is_quant_spec_zero = 1;
ch_dyn_bits = max_ch_dyn_bits[ch];
}
}
if ((gain == MAX_GAIN_INDEX) && (constraints_fulfilled == 0)) {
/* Bit consuption is exceding bit reservoir, there is no scope left for bit consumption
reduction, as gain has reached the maximum value. Hence breaking the quantization
loop. */
constraints_fulfilled = 1;
*is_gain_limited = 1;
ch_dyn_bits = max_ch_dyn_bits[ch];
}
if (!constraints_fulfilled) {
pstr_qc_out_ch[ch].global_gain++;
}
iterations++;
} while (!constraints_fulfilled);

View file

@ -38,7 +38,7 @@ IA_ERRORCODE ia_enhaacplus_enc_qc_main(
ixheaace_qc_out_element *pstr_qc_out_element, WORD32 ancillary_data_bytes,
ixheaace_aac_tables *pstr_aac_tables, WORD32 adts_flag, WORD32 aot, WORD32 stat_bits_flag,
WORD32 flag_last_element, WORD32 frame_len_long, WORD8 *ptr_scratch,
WORD32 *is_quant_spec_zero);
WORD32 *is_quant_spec_zero, WORD32 *is_gain_limited);
VOID ia_enhaacplus_enc_update_bit_reservoir(ixheaace_qc_state *pstr_qc_kernel,
ixheaace_qc_out *pstr_qc_out);

View file

@ -105,6 +105,7 @@ typedef struct ixheaace_state_struct {
ixheaace_mps_212_memory_struct *mps_pers_mem;
ixheaace_mps_515_memory_struct *mps_515_pers_mem;
WORD32 is_quant_spec_zero;
WORD32 is_gain_limited;
} ixheaace_state_struct;
typedef struct ixheaace_api_struct {

View file

@ -119,13 +119,15 @@ pWORD8 ppb_ia_enhaacplus_enc_sbr_init_fatal[IA_MAX_ERROR_SUB_CODE] = {
*****************************************************************************/
/* Non Fatal Errors */
pWORD8 ppb_ia_enhaacplus_enc_aac_exe_non_fatal[IA_MAX_ERROR_SUB_CODE] = {
(pWORD8) "Quantization zero spectrum detected"};
(pWORD8) "Quantization zero spectrum detected",
(pWORD8) "Insufficient bit reservoir for non zero spectrum"};
pWORD8 ppb_ia_enhaacplus_enc_mps_exe_non_fatal[IA_MAX_ERROR_SUB_CODE] = {
(pWORD8) "Encoding Failed", (pWORD8) "Invalid MPS data bands"};
pWORD8 ppb_ia_enhaacplus_enc_usac_exe_non_fatal[IA_MAX_ERROR_SUB_CODE] = {
(pWORD8) "Quantization zero spectrum detected"};
(pWORD8) "Quantization zero spectrum detected",
(pWORD8) "Insufficient bit reservoir for non zero spectrum"};
pWORD8 ppb_ia_enhaacplus_enc_esbr_exe_non_fatal[IA_MAX_ERROR_SUB_CODE] = {
(pWORD8) "Invalid bandwidth index encountered",