Fixes a rare integer overflow in the SILK "50% of max rate" rule
[opus.git] / src / opus_encoder.c
index 0b9d231..e9a6c25 100644 (file)
@@ -487,36 +487,27 @@ int opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_size,
 #endif
     }
 
-    if (st->stream_channels == 1 && st->prev_channels ==2 && st->silk_mode.toMono==0)
-    {
-       /* Delay stereo->mono transition by two frames so that SILK can do a smooth downmix */
-       st->silk_mode.toMono = 1;
-       st->stream_channels = 2;
-    } else {
-       st->silk_mode.toMono = 0;
-    }
-
-#ifdef FUZZING
-    /* Random mode switching */
-    if ((rand()&0xF)==0)
-    {
-       if ((rand()&0x1)==0)
-          st->mode = MODE_CELT_ONLY;
-       else
-          st->mode = MODE_SILK_ONLY;
-    } else {
-       if (st->prev_mode==MODE_CELT_ONLY)
-          st->mode = MODE_CELT_ONLY;
-       else
-          st->mode = MODE_SILK_ONLY;
-    }
-#else
     /* Mode selection depending on application and signal type */
     if (st->application == OPUS_APPLICATION_RESTRICTED_LOWDELAY)
     {
        st->mode = MODE_CELT_ONLY;
     } else if (st->user_forced_mode == OPUS_AUTO)
     {
+#ifdef FUZZING
+       /* Random mode switching */
+       if ((rand()&0xF)==0)
+       {
+          if ((rand()&0x1)==0)
+             st->mode = MODE_CELT_ONLY;
+          else
+             st->mode = MODE_SILK_ONLY;
+       } else {
+          if (st->prev_mode==MODE_CELT_ONLY)
+             st->mode = MODE_CELT_ONLY;
+          else
+             st->mode = MODE_SILK_ONLY;
+       }
+#else
        int chan;
        opus_int32 mode_voice, mode_music;
        opus_int32 threshold;
@@ -533,15 +524,25 @@ int opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_size,
            threshold += 4000;
 
        st->mode = (equiv_rate >= threshold) ? MODE_CELT_ONLY: MODE_SILK_ONLY;
+#endif
     } else {
        st->mode = st->user_forced_mode;
     }
-#endif
 
     /* Override the chosen mode to make sure we meet the requested frame size */
     if (st->mode != MODE_CELT_ONLY && frame_size < st->Fs/100)
        st->mode = MODE_CELT_ONLY;
 
+    if (st->stream_channels == 1 && st->prev_channels ==2 && st->silk_mode.toMono==0
+          && st->mode != MODE_CELT_ONLY && st->prev_mode != MODE_CELT_ONLY)
+    {
+       /* Delay stereo->mono transition by two frames so that SILK can do a smooth downmix */
+       st->silk_mode.toMono = 1;
+       st->stream_channels = 2;
+    } else {
+       st->silk_mode.toMono = 0;
+    }
+
     if (st->prev_mode > 0 &&
         ((st->mode != MODE_CELT_ONLY && st->prev_mode == MODE_CELT_ONLY) ||
     (st->mode == MODE_CELT_ONLY && st->prev_mode != MODE_CELT_ONLY)))
@@ -752,7 +753,7 @@ int opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_size,
             }
         }
         /* SILK is not allow to use more than 50% of max_data_bytes */
-        if (max_data_bytes < 2*st->silk_mode.bitRate*frame_size / (st->Fs * 8))
+        if (max_data_bytes < st->silk_mode.bitRate*frame_size / (st->Fs * 4))
            st->silk_mode.bitRate = max_data_bytes*st->Fs*4/frame_size;
 
         st->silk_mode.payloadSize_ms = 1000 * frame_size / st->Fs;
@@ -916,15 +917,19 @@ int opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_size,
         }
     }
 
-    if (st->mode != MODE_CELT_ONLY && ec_tell(&enc)+29+8*(st->mode == MODE_HYBRID) < 8*nb_compr_bytes)
+    if ( st->mode != MODE_CELT_ONLY && ec_tell(&enc)+17+20*(st->mode == MODE_HYBRID) < 8*(max_data_bytes-1))
     {
-        /* Check if we have a redundant 0-8 kHz band */
-        ec_enc_bit_logp(&enc, redundancy, 12);
+        /* For SILK mode, the redundancy is inferred from the length */
+        if (st->mode == MODE_HYBRID && (redundancy || ec_tell(&enc)+37 < 8*nb_compr_bytes))
+           ec_enc_bit_logp(&enc, redundancy, 12);
         if (redundancy)
         {
             int max_redundancy;
             ec_enc_bit_logp(&enc, celt_to_silk, 1);
-            max_redundancy = nb_compr_bytes-((ec_tell(&enc)+7)>>3)-(st->mode == MODE_HYBRID);
+            if (st->mode == MODE_HYBRID)
+               max_redundancy = (max_data_bytes-1)-nb_compr_bytes-1;
+            else
+               max_redundancy = (max_data_bytes-1)-((ec_tell(&enc)+7)>>3);
             /* Target the same bit-rate for redundancy as for the rest,
                up to a max of 257 bytes */
             redundancy_bytes = IMIN(max_redundancy, st->bitrate_bps/1600);
@@ -952,7 +957,7 @@ int opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_size,
             while(ret>2&&data[ret-1]==0)ret--;
         nb_compr_bytes = ret;
     } else {
-       nb_compr_bytes = IMIN(1275-redundancy_bytes, nb_compr_bytes);
+       nb_compr_bytes = IMIN((max_data_bytes-1)-redundancy_bytes, nb_compr_bytes);
        ec_enc_shrink(&enc, nb_compr_bytes);
     }