shithub: opus

Download patch

ref: c0f050e7439ef93e256d35377ef20954a0d13b8f
parent: c4ca21fcde457b255cef4f945934d8e451880ea3
author: Jean-Marc Valin <[email protected]>
date: Thu Sep 15 13:18:33 EDT 2011

Making sure to avoid undefined behaviour

Mainly implementing signed overflow behaviour in a way that isn't
undefined in the C standard

--- a/silk/silk_Inlines.h
+++ b/silk/silk_Inlines.h
@@ -117,7 +117,7 @@
     result = SKP_SMULWB(a32_nrm, b32_inv);                                  /* Q: 29 + a_headrm - b_headrm    */
 
     /* Compute residual by subtracting product of denominator and first approximation */
-    a32_nrm -= SKP_LSHIFT_ovflw( SKP_SMMUL(b32_nrm, result), 3 );           /* Q: a_headrm                    */
+    a32_nrm -= SKP_LSHIFT( SKP_SMMUL(b32_nrm, result), 3 );           /* Q: a_headrm                    */
 
     /* Refinement */
     result = SKP_SMLAWB(result, a32_nrm, b32_inv);                          /* Q: 29 + a_headrm - b_headrm    */
@@ -159,7 +159,7 @@
     result = SKP_LSHIFT(b32_inv, 16);                                       /* Q: 61 - b_headrm            */
 
     /* Compute residual by subtracting product of denominator and first approximation from one */
-    err_Q32 = SKP_LSHIFT_ovflw( -SKP_SMULWB(b32_nrm, b32_inv), 3 );         /* Q32                        */
+    err_Q32 = SKP_LSHIFT( (1<<29)-SKP_SMULWB(b32_nrm, b32_inv), 3 );         /* Q32                        */
 
     /* Refinement */
     result = SKP_SMLAWW(result, err_Q32, b32_inv);                          /* Q: 61 - b_headrm            */
--- a/silk/silk_MacroDebug.h
+++ b/silk/silk_MacroDebug.h
@@ -296,14 +296,6 @@
 #define SKP_MLA_ovflw(a32, b32, c32)    ((a32) + ((b32) * (c32)))
 #undef    SKP_SMLABB_ovflw
 #define SKP_SMLABB_ovflw(a32, b32, c32)    ((a32) + ((opus_int32)((opus_int16)(b32))) * (opus_int32)((opus_int16)(c32)))
-#undef    SKP_SMLABT_ovflw
-#define SKP_SMLABT_ovflw(a32, b32, c32)    ((a32) + ((opus_int32)((opus_int16)(b32))) * ((c32) >> 16))
-#undef    SKP_SMLATT_ovflw
-#define SKP_SMLATT_ovflw(a32, b32, c32)    ((a32) + ((b32) >> 16) * ((c32) >> 16))
-#undef    SKP_SMLAWB_ovflw
-#define SKP_SMLAWB_ovflw(a32, b32, c32)    ((a32) + ((((b32) >> 16) * (opus_int32)((opus_int16)(c32))) + ((((b32) & 0x0000FFFF) * (opus_int32)((opus_int16)(c32))) >> 16)))
-#undef    SKP_SMLAWT_ovflw
-#define SKP_SMLAWT_ovflw(a32, b32, c32)    ((a32) + (((b32) >> 16) * ((c32) >> 16)) + ((((b32) & 0x0000FFFF) * ((c32) >> 16)) >> 16))
 
 /* no checking needed for SKP_SMULL
    no checking needed for SKP_SMLAL
--- a/silk/silk_NSQ.c
+++ b/silk/silk_NSQ.c
@@ -353,7 +353,7 @@
         NSQ->sLTP_buf_idx++;
 
         /* Make dither dependent on quantized signal */
-        NSQ->rand_seed += pulses[ i ];
+        NSQ->rand_seed = SKP_ADD32_ovflw(NSQ->rand_seed, pulses[ i ]);
     }
 
     /* Update LPC synth buffer */
--- a/silk/silk_SigProc_FIX.h
+++ b/silk/silk_SigProc_FIX.h
@@ -398,7 +398,9 @@
     opus_uint32 x = (opus_uint32) a32;
     opus_uint32 r = (opus_uint32) rot;
     opus_uint32 m = (opus_uint32) -rot;
-    if(rot <= 0)
+    if (rot==0)
+       return a32;
+    else if(rot < 0)
         return (opus_int32) ((x << m) | (x >> (32 - m)));
     else
         return (opus_int32) ((x << (32 - r)) | (x >> r));
@@ -440,15 +442,15 @@
 /* (a32 * b32) */
 #define SKP_SMULL(a32, b32)                ((opus_int64)(a32) * /*(opus_int64)*/(b32))
 
+/* Adds two signed 32-bit values in a way that can overflow, while not relying on undefined behaviour
+   (just standard two's complement implementation-specific behaviour) */
+#define SKP_ADD32_ovflw(a, b)              ((opus_int32)((opus_uint32)(a) + (opus_uint32)(b)))
+
 /* multiply-accumulate macros that allow overflow in the addition (ie, no asserts in debug mode)*/
-#define SKP_MLA_ovflw(a32, b32, c32)       SKP_MLA(a32, b32, c32)
+#define SKP_MLA_ovflw(a32, b32, c32)       SKP_ADD32_ovflw((a32),(opus_uint32)(b32) * (opus_uint32)(c32))
 #ifndef SKP_SMLABB_ovflw
-#    define SKP_SMLABB_ovflw(a32, b32, c32)    SKP_SMLABB(a32, b32, c32)
+#    define SKP_SMLABB_ovflw(a32, b32, c32)    SKP_ADD32_ovflw((a32), (opus_int32)((opus_int16)(b32)) * (opus_int32)((opus_int16)(c32)))
 #endif
-#define SKP_SMLABT_ovflw(a32, b32, c32)    SKP_SMLABT(a32, b32, c32)
-#define SKP_SMLATT_ovflw(a32, b32, c32)    SKP_SMLATT(a32, b32, c32)
-#define SKP_SMLAWB_ovflw(a32, b32, c32)    SKP_SMLAWB(a32, b32, c32)
-#define SKP_SMLAWT_ovflw(a32, b32, c32)    SKP_SMLAWT(a32, b32, c32)
 
 #define SKP_DIV32_16(a32, b16)             ((opus_int32)((a32) / (b16)))
 #define SKP_DIV32(a32, b32)                ((opus_int32)((a32) / (b32)))
--- a/silk/silk_decode_core.c
+++ b/silk/silk_decode_core.c
@@ -73,7 +73,7 @@
         psDec->exc_Q10[ i ] += offset_Q10;
         psDec->exc_Q10[ i ] ^= SKP_RSHIFT( rand_seed, 31 );
 
-        rand_seed += pulses[ i ];
+        rand_seed = SKP_ADD32_ovflw(rand_seed, pulses[ i ]);
     }
 
 #ifdef SAVE_ALL_INTERNAL_DATA