Skip to content

Commit 13b5850

Browse files
pythongh-96821: Fix undefined behaviour in audioop.c
Left-shifting negative numbers is undefined behaviour. Fortunately, multiplication works just as well, is defined behaviour, and gets compiled to the same machine code as before by optimizing compilers.
1 parent bbc24b2 commit 13b5850

File tree

1 file changed

+16
-14
lines changed

1 file changed

+16
-14
lines changed

Modules/audioop.c

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ search(int16_t val, const int16_t *table, int size)
6565
if (val <= *table++)
6666
return (i);
6767
}
68+
assert(0 <= size);
69+
assert(size < INT16_MAX);
6870
return (size);
6971
}
7072
#define st_ulaw2linear16(uc) (_st_ulaw2linear16[uc])
@@ -170,7 +172,7 @@ st_14linear2ulaw(int16_t pcm_val) /* 2's complement (14-bit range) */
170172
if (seg >= 8) /* out of range, return maximum value. */
171173
return (unsigned char) (0x7F ^ mask);
172174
else {
173-
uval = (unsigned char) (seg << 4) | ((pcm_val >> (seg + 1)) & 0xF);
175+
uval = (unsigned char) (seg * (1 << 4)) | ((pcm_val >> (seg + 1)) & 0xF);
174176
return (uval ^ mask);
175177
}
176178

@@ -259,7 +261,7 @@ st_linear2alaw(int16_t pcm_val) /* 2's complement (13-bit range) */
259261
if (seg >= 8) /* out of range, return maximum value. */
260262
return (unsigned char) (0x7F ^ mask);
261263
else {
262-
aval = (unsigned char) seg << SEG_SHIFT;
264+
aval = (unsigned char) seg * (1 << SEG_SHIFT);
263265
if (seg < 2)
264266
aval |= (pcm_val >> 1) & QUANT_MASK;
265267
else
@@ -300,13 +302,13 @@ static const int stepsizeTable[89] = {
300302
#ifdef WORDS_BIGENDIAN
301303
#define GETINT24(cp, i) ( \
302304
((unsigned char *)(cp) + (i))[2] + \
303-
(((unsigned char *)(cp) + (i))[1] << 8) + \
304-
(((signed char *)(cp) + (i))[0] << 16) )
305+
(((unsigned char *)(cp) + (i))[1] * (1 << 8)) + \
306+
(((signed char *)(cp) + (i))[0] * (1 << 16)) )
305307
#else
306308
#define GETINT24(cp, i) ( \
307309
((unsigned char *)(cp) + (i))[0] + \
308-
(((unsigned char *)(cp) + (i))[1] << 8) + \
309-
(((signed char *)(cp) + (i))[2] << 16) )
310+
(((unsigned char *)(cp) + (i))[1] * (1 << 8)) + \
311+
(((signed char *)(cp) + (i))[2] * (1 << 16)) )
310312
#endif
311313

312314

@@ -347,10 +349,10 @@ static const int stepsizeTable[89] = {
347349
} while(0)
348350

349351

350-
#define GETSAMPLE32(size, cp, i) ( \
351-
(size == 1) ? (int)GETINT8((cp), (i)) << 24 : \
352-
(size == 2) ? (int)GETINT16((cp), (i)) << 16 : \
353-
(size == 3) ? (int)GETINT24((cp), (i)) << 8 : \
352+
#define GETSAMPLE32(size, cp, i) ( \
353+
(size == 1) ? (int)GETINT8((cp), (i)) * (1 << 24) : \
354+
(size == 2) ? (int)GETINT16((cp), (i)) * (1 << 16) : \
355+
(size == 3) ? (int)GETINT24((cp), (i)) * (1 << 8) : \
354356
(int)GETINT32((cp), (i)))
355357

356358
#define SETSAMPLE32(size, cp, i, val) do { \
@@ -1558,7 +1560,7 @@ audioop_ulaw2lin_impl(PyObject *module, Py_buffer *fragment, int width)
15581560

15591561
cp = fragment->buf;
15601562
for (i = 0; i < fragment->len*width; i += width) {
1561-
int val = st_ulaw2linear16(*cp++) << 16;
1563+
int val = st_ulaw2linear16(*cp++) * (1 << 16);
15621564
SETSAMPLE32(width, ncp, i, val);
15631565
}
15641566
return rv;
@@ -1632,7 +1634,7 @@ audioop_alaw2lin_impl(PyObject *module, Py_buffer *fragment, int width)
16321634
cp = fragment->buf;
16331635

16341636
for (i = 0; i < fragment->len*width; i += width) {
1635-
val = st_alaw2linear16(*cp++) << 16;
1637+
val = st_alaw2linear16(*cp++) * (1 << 16);
16361638
SETSAMPLE32(width, ncp, i, val);
16371639
}
16381640
return rv;
@@ -1757,7 +1759,7 @@ audioop_lin2adpcm_impl(PyObject *module, Py_buffer *fragment, int width,
17571759

17581760
/* Step 6 - Output value */
17591761
if ( bufferstep ) {
1760-
outputbuffer = (delta << 4) & 0xf0;
1762+
outputbuffer = (delta * (1 << 4)) & 0xf0;
17611763
} else {
17621764
*ncp++ = (delta & 0x0f) | outputbuffer;
17631765
}
@@ -1875,7 +1877,7 @@ audioop_adpcm2lin_impl(PyObject *module, Py_buffer *fragment, int width,
18751877
step = stepsizeTable[index];
18761878

18771879
/* Step 6 - Output value */
1878-
SETSAMPLE32(width, ncp, i, valpred << 16);
1880+
SETSAMPLE32(width, ncp, i, valpred * (1 << 16));
18791881
}
18801882

18811883
rv = Py_BuildValue("(O(ii))", str, valpred, index);

0 commit comments

Comments
 (0)