Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-96821: Fix undefined behaviour in audioop.c #96923

Merged
merged 11 commits into from
Oct 10, 2022
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)) + \
matthiasgoergens marked this conversation as resolved.
Show resolved Hide resolved
(((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