Skip to content

Commit edffe56

Browse files
committed
Add PSHR32_ovflw() and use it in IMDCT
Prevents integer overflow UB in the shift rounding when the signal blows up on bad bitstreams (if it triggers, the signal was already unusable anyway).
1 parent fba923d commit edffe56

File tree

4 files changed

+10
-4
lines changed

4 files changed

+10
-4
lines changed

celt/arch.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,8 @@ static OPUS_INLINE int celt_isnan(float x)
330330
#define SUB32(a,b) ((a)-(b))
331331
#define ADD32_ovflw(a,b) ((a)+(b))
332332
#define SUB32_ovflw(a,b) ((a)-(b))
333+
#define PSHR32_ovflw(a,shift) (a)
334+
333335
#define MULT16_16_16(a,b) ((a)*(b))
334336
#define MULT16_16(a,b) ((opus_val32)(a)*(opus_val32)(b))
335337
#define MAC16_16(c,a,b) ((c)+(opus_val32)(a)*(opus_val32)(b))

celt/fixed_debug.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ extern opus_int64 celt_mips;
6969
/* Avoid MSVC warning C4146: unary minus operator applied to unsigned type */
7070
/** Negate 32-bit value, ignore any overflows */
7171
#define NEG32_ovflw(a) (celt_mips+=2,(opus_val32)(0-(opus_uint32)(a)))
72+
/** 32-bit arithmetic shift right with rounding-to-nearest, ignoring overflows */
73+
#define PSHR32_ovflw(a,shift) (SHR32(ADD32_ovflw(a, (EXTEND32(1)<<(shift)>>1)),shift))
7274

7375
static OPUS_INLINE short NEG16(int x)
7476
{

celt/fixed_generic.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,8 @@
147147
/* Avoid MSVC warning C4146: unary minus operator applied to unsigned type */
148148
/** Negate 32-bit value, ignore any overflows */
149149
#define NEG32_ovflw(a) ((opus_val32)(0-(opus_uint32)(a)))
150+
/** 32-bit arithmetic shift right with rounding-to-nearest, ignoring overflows */
151+
#define PSHR32_ovflw(a,shift) (SHR32(ADD32_ovflw(a, (EXTEND32(1)<<(shift)>>1)),shift))
150152

151153
/** 16x16 multiplication where the result fits in 16 bits */
152154
#define MULT16_16_16(a,b) ((((opus_val16)(a))*((opus_val16)(b))))

celt/mdct.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -330,8 +330,8 @@ void clt_mdct_backward_c(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_sca
330330
t0 = t[i];
331331
t1 = t[N4+i];
332332
/* We'd scale up by 2 here, but instead it's done when mixing the windows */
333-
yr = PSHR32(ADD32_ovflw(S_MUL(re,t0), S_MUL(im,t1)), IMDCT_HEADROOM);
334-
yi = PSHR32(SUB32_ovflw(S_MUL(re,t1), S_MUL(im,t0)), IMDCT_HEADROOM);
333+
yr = PSHR32_ovflw(ADD32_ovflw(S_MUL(re,t0), S_MUL(im,t1)), IMDCT_HEADROOM);
334+
yi = PSHR32_ovflw(SUB32_ovflw(S_MUL(re,t1), S_MUL(im,t0)), IMDCT_HEADROOM);
335335
/* We swap real and imag because we're using an FFT instead of an IFFT. */
336336
re = yp1[1];
337337
im = yp1[0];
@@ -341,8 +341,8 @@ void clt_mdct_backward_c(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_sca
341341
t0 = t[(N4-i-1)];
342342
t1 = t[(N2-i-1)];
343343
/* We'd scale up by 2 here, but instead it's done when mixing the windows */
344-
yr = PSHR32(ADD32_ovflw(S_MUL(re,t0), S_MUL(im,t1)), IMDCT_HEADROOM);
345-
yi = PSHR32(SUB32_ovflw(S_MUL(re,t1), S_MUL(im,t0)), IMDCT_HEADROOM);
344+
yr = PSHR32_ovflw(ADD32_ovflw(S_MUL(re,t0), S_MUL(im,t1)), IMDCT_HEADROOM);
345+
yi = PSHR32_ovflw(SUB32_ovflw(S_MUL(re,t1), S_MUL(im,t0)), IMDCT_HEADROOM);
346346
yp1[0] = yr;
347347
yp0[1] = yi;
348348
yp0 += 2;

0 commit comments

Comments
 (0)