shithub: opus

Download patch

ref: 60b8f5b80307c1ecb1070f602074c791444c52bc
parent: a013aa047760ec7508aec5755c225aa3b23a2581
author: Jean-Marc Valin <jeanmarcv@google.com>
date: Thu Apr 3 10:45:24 EDT 2025

Add SHL32_ovflw() and use it in IMDCT

Prevents integer overflow UB in the headroom left shift when
the signal blows up on bad bitstreams (if it triggers, the
signal was already unusable anyway).

--- a/celt/arch.h
+++ b/celt/arch.h
@@ -330,6 +330,7 @@
 #define SUB32(a,b) ((a)-(b))
 #define ADD32_ovflw(a,b) ((a)+(b))
 #define SUB32_ovflw(a,b) ((a)-(b))
+#define SHL32_ovflw(a,shift) (a)
 #define PSHR32_ovflw(a,shift) (a)
 
 #define MULT16_16_16(a,b)     ((a)*(b))
--- a/celt/fixed_debug.h
+++ b/celt/fixed_debug.h
@@ -69,6 +69,8 @@
 /* Avoid MSVC warning C4146: unary minus operator applied to unsigned type */
 /** Negate 32-bit value, ignore any overflows */
 #define NEG32_ovflw(a) (celt_mips+=2,(opus_val32)(0-(opus_uint32)(a)))
+/** 32-bit shift left, ignoring overflows */
+#define SHL32_ovflw(a,shift) ((opus_int32)((opus_uint32)(a)<<(shift)))
 /** 32-bit arithmetic shift right with rounding-to-nearest, ignoring overflows */
 #define PSHR32_ovflw(a,shift) (SHR32(ADD32_ovflw(a, (EXTEND32(1)<<(shift)>>1)),shift))
 
--- a/celt/fixed_generic.h
+++ b/celt/fixed_generic.h
@@ -147,6 +147,8 @@
 /* Avoid MSVC warning C4146: unary minus operator applied to unsigned type */
 /** Negate 32-bit value, ignore any overflows */
 #define NEG32_ovflw(a) ((opus_val32)(0-(opus_uint32)(a)))
+/** 32-bit shift left, ignoring overflows */
+#define SHL32_ovflw(a,shift) SHL32(a,shift)
 /** 32-bit arithmetic shift right with rounding-to-nearest, ignoring overflows */
 #define PSHR32_ovflw(a,shift) (SHR32(ADD32_ovflw(a, (EXTEND32(1)<<(shift)>>1)),shift))
 
--- a/celt/mdct.c
+++ b/celt/mdct.c
@@ -297,8 +297,8 @@
          kiss_fft_scalar yr, yi;
          opus_val32 x1, x2;
          rev = *bitrev++;
-         x1 = SHL32(*xp1, IMDCT_HEADROOM);
-         x2 = SHL32(*xp2, IMDCT_HEADROOM);
+         x1 = SHL32_ovflw(*xp1, IMDCT_HEADROOM);
+         x2 = SHL32_ovflw(*xp2, IMDCT_HEADROOM);
          yr = ADD32_ovflw(S_MUL(x2, t[i]), S_MUL(x1, t[N4+i]));
          yi = SUB32_ovflw(S_MUL(x1, t[i]), S_MUL(x2, t[N4+i]));
          /* We swap real and imag because we use an FFT instead of an IFFT. */
--