diff options
author | Matthias Görgens <matthias.goergens@gmail.com> | 2022-10-10 16:12:29 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-10-10 16:12:29 (GMT) |
commit | 553d3c10172254b190078c50eb9f8e60522c8f41 (patch) | |
tree | 3542a1184d0c5769d10d3ecd14b9e93d00d4959c /Modules | |
parent | dfcdee4a18ece6f7c4fe1aa5830ee861f8b15b24 (diff) | |
download | cpython-553d3c10172254b190078c50eb9f8e60522c8f41.zip cpython-553d3c10172254b190078c50eb9f8e60522c8f41.tar.gz cpython-553d3c10172254b190078c50eb9f8e60522c8f41.tar.bz2 |
gh-96821: Fix undefined behaviour in `audioop.c` (#96923)
* gh-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>
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/audioop.c | 27 |
1 files changed, 15 insertions, 12 deletions
diff --git a/Modules/audioop.c b/Modules/audioop.c index d74e634..c29a3e8 100644 --- a/Modules/audioop.c +++ b/Modules/audioop.c @@ -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++) { @@ -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); } @@ -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 @@ -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 { \ @@ -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; @@ -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; @@ -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; } @@ -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); |