From 84af51d1b3a55ea3a0c860bb2f2ff99039d621cd Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sun, 28 Jun 2015 17:51:40 +0300 Subject: Issue #24456: Fixed possible buffer over-read in adpcm2lin() and lin2adpcm() functions of the audioop module. Fixed SystemError when the state is not a tuple. Fixed possible memory leak. --- Lib/test/test_audioop.py | 15 +++++++++++++++ Misc/NEWS | 4 ++++ Modules/audioop.c | 38 ++++++++++++++++++++++++++++++-------- 3 files changed, 49 insertions(+), 8 deletions(-) diff --git a/Lib/test/test_audioop.py b/Lib/test/test_audioop.py index ceaf2a3..4af7350 100644 --- a/Lib/test/test_audioop.py +++ b/Lib/test/test_audioop.py @@ -210,6 +210,21 @@ class TestAudioop(unittest.TestCase): self.assertEqual(audioop.lin2adpcm(b'\0' * w * 10, w, None), (b'\0' * 5, (0, 0))) + def test_invalid_adpcm_state(self): + # state must be a tuple or None, not an integer + self.assertRaises(TypeError, audioop.adpcm2lin, b'\0', 1, 555) + self.assertRaises(TypeError, audioop.lin2adpcm, b'\0', 1, 555) + # Issues #24456, #24457: index out of range + self.assertRaises(ValueError, audioop.adpcm2lin, b'\0', 1, (0, -1)) + self.assertRaises(ValueError, audioop.adpcm2lin, b'\0', 1, (0, 89)) + self.assertRaises(ValueError, audioop.lin2adpcm, b'\0', 1, (0, -1)) + self.assertRaises(ValueError, audioop.lin2adpcm, b'\0', 1, (0, 89)) + # value out of range + self.assertRaises(ValueError, audioop.adpcm2lin, b'\0', 1, (-0x8001, 0)) + self.assertRaises(ValueError, audioop.adpcm2lin, b'\0', 1, (0x8000, 0)) + self.assertRaises(ValueError, audioop.lin2adpcm, b'\0', 1, (-0x8001, 0)) + self.assertRaises(ValueError, audioop.lin2adpcm, b'\0', 1, (0x8000, 0)) + def test_lin2alaw(self): self.assertEqual(audioop.lin2alaw(datas[1], 1), b'\xd5\x87\xa4\x24\xaa\x2a\x5a') diff --git a/Misc/NEWS b/Misc/NEWS index 1496398..9418ad2 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -30,6 +30,10 @@ Core and Builtins Library ------- +- Issue #24456: Fixed possible buffer over-read in adpcm2lin() and lin2adpcm() + functions of the audioop module. Fixed SystemError when the state is not a + tuple. Fixed possible memory leak. + - Issue #24481: Fix possible memory corruption with large profiler info strings in hotshot. diff --git a/Modules/audioop.c b/Modules/audioop.c index 0282c7e..4d3b679 100644 --- a/Modules/audioop.c +++ b/Modules/audioop.c @@ -1420,18 +1420,29 @@ audioop_lin2adpcm(PyObject *self, PyObject *args) if (!audioop_check_parameters(len, size)) return NULL; - str = PyString_FromStringAndSize(NULL, len/(size*2)); - if ( str == 0 ) - return 0; - ncp = (signed char *)PyString_AsString(str); - /* Decode state, should have (value, step) */ if ( state == Py_None ) { /* First time, it seems. Set defaults */ valpred = 0; index = 0; - } else if ( !PyArg_ParseTuple(state, "ii", &valpred, &index) ) + } + else if (!PyTuple_Check(state)) { + PyErr_SetString(PyExc_TypeError, "state must be a tuple or None"); + return NULL; + } + else if (!PyArg_ParseTuple(state, "ii", &valpred, &index)) { + return NULL; + } + else if (valpred >= 0x8000 || valpred < -0x8000 || + (size_t)index >= sizeof(stepsizeTable)/sizeof(stepsizeTable[0])) { + PyErr_SetString(PyExc_ValueError, "bad state"); + return NULL; + } + + str = PyString_FromStringAndSize(NULL, len/(size*2)); + if ( str == 0 ) return 0; + ncp = (signed char *)PyString_AsString(str); step = stepsizeTable[index]; bufferstep = 1; @@ -1529,8 +1540,19 @@ audioop_adpcm2lin(PyObject *self, PyObject *args) /* First time, it seems. Set defaults */ valpred = 0; index = 0; - } else if ( !PyArg_ParseTuple(state, "ii", &valpred, &index) ) - return 0; + } + else if (!PyTuple_Check(state)) { + PyErr_SetString(PyExc_TypeError, "state must be a tuple or None"); + return NULL; + } + else if (!PyArg_ParseTuple(state, "ii", &valpred, &index)) { + return NULL; + } + else if (valpred >= 0x8000 || valpred < -0x8000 || + (size_t)index >= sizeof(stepsizeTable)/sizeof(stepsizeTable[0])) { + PyErr_SetString(PyExc_ValueError, "bad state"); + return NULL; + } if (len > (INT_MAX/2)/size) { PyErr_SetString(PyExc_MemoryError, -- cgit v0.12