Commit b9b9e7b4 authored by Serhiy Storchaka's avatar Serhiy Storchaka

Issue #24456: Fixed possible buffer over-read in adpcm2lin() and lin2adpcm()

functions of the audioop module.
parents eab77040 449e2be1
...@@ -273,6 +273,16 @@ class TestAudioop(unittest.TestCase): ...@@ -273,6 +273,16 @@ class TestAudioop(unittest.TestCase):
# state must be a tuple or None, not an integer # state must be a tuple or None, not an integer
self.assertRaises(TypeError, audioop.adpcm2lin, b'\0', 1, 555) self.assertRaises(TypeError, audioop.adpcm2lin, b'\0', 1, 555)
self.assertRaises(TypeError, audioop.lin2adpcm, 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): def test_lin2alaw(self):
self.assertEqual(audioop.lin2alaw(datas[1], 1), self.assertEqual(audioop.lin2alaw(datas[1], 1),
......
...@@ -25,6 +25,9 @@ Core and Builtins ...@@ -25,6 +25,9 @@ Core and Builtins
Library Library
------- -------
- Issue #24456: Fixed possible buffer over-read in adpcm2lin() and lin2adpcm()
functions of the audioop module.
- Issue #24336: The contextmanager decorator now works with functions with - Issue #24336: The contextmanager decorator now works with functions with
keyword arguments called "func" and "self". Patch by Martin Panter. keyword arguments called "func" and "self". Patch by Martin Panter.
......
...@@ -1627,23 +1627,30 @@ audioop_lin2adpcm_impl(PyModuleDef *module, Py_buffer *fragment, int width, ...@@ -1627,23 +1627,30 @@ audioop_lin2adpcm_impl(PyModuleDef *module, Py_buffer *fragment, int width,
if (!audioop_check_parameters(fragment->len, width)) if (!audioop_check_parameters(fragment->len, width))
return NULL; return NULL;
str = PyBytes_FromStringAndSize(NULL, fragment->len/(width*2));
if (str == NULL)
return NULL;
ncp = (signed char *)PyBytes_AsString(str);
/* Decode state, should have (value, step) */ /* Decode state, should have (value, step) */
if ( state == Py_None ) { if ( state == Py_None ) {
/* First time, it seems. Set defaults */ /* First time, it seems. Set defaults */
valpred = 0; valpred = 0;
index = 0; index = 0;
} else if (!PyTuple_Check(state)) { }
else if (!PyTuple_Check(state)) {
PyErr_SetString(PyExc_TypeError, "state must be a tuple or None"); PyErr_SetString(PyExc_TypeError, "state must be a tuple or None");
goto exit; return NULL;
} else if (!PyArg_ParseTuple(state, "ii", &valpred, &index)) { }
goto exit; else if (!PyArg_ParseTuple(state, "ii", &valpred, &index)) {
return NULL;
}
else if (valpred >= 0x8000 || valpred < -0x8000 ||
(size_t)index >= Py_ARRAY_LENGTH(stepsizeTable)) {
PyErr_SetString(PyExc_ValueError, "bad state");
return NULL;
} }
str = PyBytes_FromStringAndSize(NULL, fragment->len/(width*2));
if (str == NULL)
return NULL;
ncp = (signed char *)PyBytes_AsString(str);
step = stepsizeTable[index]; step = stepsizeTable[index];
bufferstep = 1; bufferstep = 1;
...@@ -1718,8 +1725,6 @@ audioop_lin2adpcm_impl(PyModuleDef *module, Py_buffer *fragment, int width, ...@@ -1718,8 +1725,6 @@ audioop_lin2adpcm_impl(PyModuleDef *module, Py_buffer *fragment, int width,
bufferstep = !bufferstep; bufferstep = !bufferstep;
} }
rv = Py_BuildValue("(O(ii))", str, valpred, index); rv = Py_BuildValue("(O(ii))", str, valpred, index);
exit:
Py_DECREF(str); Py_DECREF(str);
return rv; return rv;
} }
...@@ -1755,11 +1760,19 @@ audioop_adpcm2lin_impl(PyModuleDef *module, Py_buffer *fragment, int width, ...@@ -1755,11 +1760,19 @@ audioop_adpcm2lin_impl(PyModuleDef *module, Py_buffer *fragment, int width,
/* First time, it seems. Set defaults */ /* First time, it seems. Set defaults */
valpred = 0; valpred = 0;
index = 0; index = 0;
} else if (!PyTuple_Check(state)) { }
else if (!PyTuple_Check(state)) {
PyErr_SetString(PyExc_TypeError, "state must be a tuple or None"); PyErr_SetString(PyExc_TypeError, "state must be a tuple or None");
return NULL; return NULL;
} else if (!PyArg_ParseTuple(state, "ii", &valpred, &index)) }
else if (!PyArg_ParseTuple(state, "ii", &valpred, &index)) {
return NULL;
}
else if (valpred >= 0x8000 || valpred < -0x8000 ||
(size_t)index >= Py_ARRAY_LENGTH(stepsizeTable)) {
PyErr_SetString(PyExc_ValueError, "bad state");
return NULL; return NULL;
}
if (fragment->len > (PY_SSIZE_T_MAX/2)/width) { if (fragment->len > (PY_SSIZE_T_MAX/2)/width) {
PyErr_SetString(PyExc_MemoryError, PyErr_SetString(PyExc_MemoryError,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment