shithub: opus

Download patch

ref: 367c39486618fe6a6f9ffe85e834d59cae241253
parent: 7aecadda2f72cbf1f55209293dc63e01bb743035
author: Jean-Marc Valin <[email protected]>
date: Thu Apr 12 07:07:21 EDT 2012

Fixes several overflows in the CELT fixed-point

These were all mostly benign and would at worst result in (rare)
suboptimal encoder decisions rather than signal corruption.

--- a/celt/bands.c
+++ b/celt/bands.c
@@ -249,7 +249,7 @@
             prev2 = MAX16(prev2,prev2logE[m->nbEBands+i]);
          }
          Ediff = EXTEND32(logE[c*m->nbEBands+i])-EXTEND32(MIN16(prev1,prev2));
-         Ediff = MAX16(0, Ediff);
+         Ediff = MAX32(0, Ediff);
 
 #ifdef FIXED_POINT
          if (Ediff < 16384)
--- a/celt/celt.c
+++ b/celt/celt.c
@@ -607,7 +607,7 @@
       /* Just add the right channel if we're in stereo */
       if (C==2)
          for (j=0;j<N;j++)
-            tmp[j] = ADD16(tmp[j],X[N0+j+(m->eBands[i]<<LM)]);
+            tmp[j] = ADD16(SHR16(tmp[j], 1),SHR16(X[N0+j+(m->eBands[i]<<LM)], 1));
       L1 = l1_metric(tmp, N, isTransient ? LM : 0, N>>LM);
       best_L1 = L1;
       /*printf ("%f ", L1);*/
--- a/celt/fixed_debug.h
+++ b/celt/fixed_debug.h
@@ -154,17 +154,18 @@
    celt_mips+=2;
    return res;
 }
-static inline int SHL32(long long a, int shift)
+#define SHL32(a, shift) SHL32_(a, shift, __FILE__, __LINE__)
+static inline int SHL32_(long long a, int shift, char *file, int line)
 {
    long long  res;
    if (!VERIFY_INT(a) || !VERIFY_SHORT(shift))
    {
-      fprintf (stderr, "SHL32: inputs are not int: %d %d\n", (int)a, shift);
+      fprintf (stderr, "SHL32: inputs are not int: %lld %d in %s: line %d\n", a, shift, file, line);
    }
    res = a<<shift;
    if (!VERIFY_INT(res))
    {
-      fprintf (stderr, "SHL32: output is not int: %d\n", (int)res);
+      fprintf (stderr, "SHL32: output is not int: %lld<<%d = %lld in %s: line %d\n", a, shift, res, file, line);
    }
    celt_mips+=2;
    return res;
--- a/celt/mathops.c
+++ b/celt/mathops.c
@@ -75,9 +75,15 @@
    b = VSHR32(b,shift);
    /* 16-bit reciprocal */
    rcp = ROUND16(celt_rcp(ROUND16(b,16)),3);
-   result = SHL32(MULT16_32_Q15(rcp, a),2);
-   rem = a-MULT32_32_Q31(result, b);
-   result += SHL32(MULT16_32_Q15(rcp, rem),2);
+   result = MULT16_32_Q15(rcp, a);
+   rem = PSHR32(a,2)-MULT32_32_Q31(result, b);
+   result = ADD32(result, SHL32(MULT16_32_Q15(rcp, rem),2));
+   if (result >= 536870912)       /*  2^29 */
+      return 2147483647;          /*  2^31 - 1 */
+   else if (result <= -536870912) /* -2^29 */
+      return -2147483647;         /* -2^31 */
+   else
+      return SHL32(result, 2);
    return result;
 }
 
--- a/celt/quant_bands.c
+++ b/celt/quant_bands.c
@@ -146,11 +146,11 @@
    c=0; do {
       for (i=start;i<end;i++)
       {
-         opus_val16 d = SHR16(SUB16(eBands[i+c*len], oldEBands[i+c*len]),2);
+         opus_val16 d = SUB16(SHR16(eBands[i+c*len], 3), SHR16(oldEBands[i+c*len], 3));
          dist = MAC16_16(dist, d,d);
       }
    } while (++c<C);
-   return MIN32(200,SHR32(dist,2*DB_SHIFT-4));
+   return MIN32(200,SHR32(dist,2*DB_SHIFT-6));
 }
 
 static int quant_coarse_energy_impl(const CELTMode *m, int start, int end,