Skip to content

Commit

Permalink
pythongh-96821: Fix undefined behaviour in audioop.c (python#96923)
Browse files Browse the repository at this point in the history
* 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.

Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>
  • Loading branch information
2 people authored and mpage committed Oct 11, 2022
1 parent fbfd13b commit 6d91946
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix undefined behaviour in ``audioop.c``.
27 changes: 15 additions & 12 deletions Modules/audioop.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ static const int16_t seg_uend[8] = {
static int16_t
search(int16_t val, const int16_t *table, int size)
{
assert(0 <= size);
assert(size < INT16_MAX);
int i;

for (i = 0; i < size; i++) {
Expand Down Expand Up @@ -170,6 +172,7 @@ st_14linear2ulaw(int16_t pcm_val) /* 2's complement (14-bit range) */
if (seg >= 8) /* out of range, return maximum value. */
return (unsigned char) (0x7F ^ mask);
else {
assert(seg >= 0);
uval = (unsigned char) (seg << 4) | ((pcm_val >> (seg + 1)) & 0xF);
return (uval ^ mask);
}
Expand Down Expand Up @@ -300,13 +303,13 @@ static const int stepsizeTable[89] = {
#ifdef WORDS_BIGENDIAN
#define GETINT24(cp, i) ( \
((unsigned char *)(cp) + (i))[2] + \
(((unsigned char *)(cp) + (i))[1] << 8) + \
(((signed char *)(cp) + (i))[0] << 16) )
(((unsigned char *)(cp) + (i))[1] * (1 << 8)) + \
(((signed char *)(cp) + (i))[0] * (1 << 16)) )
#else
#define GETINT24(cp, i) ( \
((unsigned char *)(cp) + (i))[0] + \
(((unsigned char *)(cp) + (i))[1] << 8) + \
(((signed char *)(cp) + (i))[2] << 16) )
(((unsigned char *)(cp) + (i))[1] * (1 << 8)) + \
(((signed char *)(cp) + (i))[2] * (1 << 16)) )
#endif


Expand Down Expand Up @@ -347,10 +350,10 @@ static const int stepsizeTable[89] = {
} while(0)


#define GETSAMPLE32(size, cp, i) ( \
(size == 1) ? (int)GETINT8((cp), (i)) << 24 : \
(size == 2) ? (int)GETINT16((cp), (i)) << 16 : \
(size == 3) ? (int)GETINT24((cp), (i)) << 8 : \
#define GETSAMPLE32(size, cp, i) ( \
(size == 1) ? (int)GETINT8((cp), (i)) * (1 << 24) : \
(size == 2) ? (int)GETINT16((cp), (i)) * (1 << 16) : \
(size == 3) ? (int)GETINT24((cp), (i)) * (1 << 8) : \
(int)GETINT32((cp), (i)))

#define SETSAMPLE32(size, cp, i, val) do { \
Expand Down Expand Up @@ -1558,7 +1561,7 @@ audioop_ulaw2lin_impl(PyObject *module, Py_buffer *fragment, int width)

cp = fragment->buf;
for (i = 0; i < fragment->len*width; i += width) {
int val = st_ulaw2linear16(*cp++) << 16;
int val = st_ulaw2linear16(*cp++) * (1 << 16);
SETSAMPLE32(width, ncp, i, val);
}
return rv;
Expand Down Expand Up @@ -1632,7 +1635,7 @@ audioop_alaw2lin_impl(PyObject *module, Py_buffer *fragment, int width)
cp = fragment->buf;

for (i = 0; i < fragment->len*width; i += width) {
val = st_alaw2linear16(*cp++) << 16;
val = st_alaw2linear16(*cp++) * (1 << 16);
SETSAMPLE32(width, ncp, i, val);
}
return rv;
Expand Down Expand Up @@ -1757,7 +1760,7 @@ audioop_lin2adpcm_impl(PyObject *module, Py_buffer *fragment, int width,

/* Step 6 - Output value */
if ( bufferstep ) {
outputbuffer = (delta << 4) & 0xf0;
outputbuffer = (delta * (1 << 4)) & 0xf0;
} else {
*ncp++ = (delta & 0x0f) | outputbuffer;
}
Expand Down Expand Up @@ -1875,7 +1878,7 @@ audioop_adpcm2lin_impl(PyObject *module, Py_buffer *fragment, int width,
step = stepsizeTable[index];

/* Step 6 - Output value */
SETSAMPLE32(width, ncp, i, valpred << 16);
SETSAMPLE32(width, ncp, i, valpred * (1 << 16));
}

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

0 comments on commit 6d91946

Please sign in to comment.