Usage of extract_l() with values out of range
Basic info
- Float reference:
- Encoder (float):
- Decoder (float):
- Fixed point:
- Encoder (fixed): 7bf796ef
- Decoder (fixed):
Bug description
In several places extract_l() is used to convert a Word32 to a Word16, but this will most likely cause unexpected results if the values is out of range for a Word16 and there is no check of any sort.
One example: for the encoder the following test case triggers a out of range condition in estDownmixGain_fx()
IVAS_cod -masa 2 ../ltv/ltv48_MASA2TC.met -dtx -max_band swb 13200 32 ../ltv/ltv48_MASA2TC_32khz.wav out.192
For any usage of extract_l() where its not about separating bit fields but converting numbers, it is recommended to add a check like this:
assert( value32 <= MAX_16 && value32 >= MIN_16 ); value16 = extract_l( value32 );
diff --git a/lib_enc/ivas_stereo_ica_enc_fx.c b/lib_enc/ivas_stereo_ica_enc_fx.c
index 234652072..c3f420f93 100644
--- a/lib_enc/ivas_stereo_ica_enc_fx.c
+++ b/lib_enc/ivas_stereo_ica_enc_fx.c
@@ -1304,9 +1304,18 @@ static void estDownmixGain_fx(
currentGain_log10 = BASOP_Util_Log10( L_deposit_h( currentGain ), currentGain_e ); // Output in Q25
// multiplication result will be Q25 should be fit to Q15 hence right shift by 10.
// Q25 - Q10 = Q15
+#if 1
+ Word32 checkv;
+ checkv = L_shr( Madd_32_16( Mpy_32_16_1( prevTargetGain_log10, alpha ), currentGain_log10, sub( MAX_16, alpha ) ), Q10 );
+ assert( checkv <= MAX_16 && checkv >= MIN_16 );
+ currentGain = extract_l( checkv ); /* Q15 */
+ currentGain_e = 0;
+ move16();
+#else
currentGain = extract_l( L_shr( Madd_32_16( Mpy_32_16_1( prevTargetGain_log10, alpha ), currentGain_log10, sub( MAX_16, alpha ) ), Q10 ) ); /* Q15 */
currentGain_e = 0;
move16();
+#endif
test();
IF( EQ_16( element_mode, IVAS_CPE_TD ) && hStereoClassif != NULL )
Ways to reproduce
- Add assert as described above.
- Run
IVAS_cod -masa 2 ../ltv/ltv48_MASA2TC.met -dtx -max_band swb 13200 32 ../ltv/ltv48_MASA2TC_32khz.wav out.192