Skip to content

Commit

Permalink
Merged revisions 82492 via svnmerge from
Browse files Browse the repository at this point in the history
svn+ssh://pythondev@svn.python.org/python/trunk

........
  r82492 | victor.stinner | 2010-07-03 15:36:19 +0200 (sam., 03 juil. 2010) | 3 lines

  Issue #7673: Fix security vulnerability (CVE-2010-2089) in the audioop module,
  ensure that the input string length is a multiple of the frame size
........
  • Loading branch information
Victor Stinner committed Jul 3, 2010
1 parent 4833e5b commit bc5c54b
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 74 deletions.
33 changes: 33 additions & 0 deletions Lib/test/test_audioop.py
Expand Up @@ -20,6 +20,12 @@ def gendata4():

data = [gendata1(), gendata2(), gendata4()]

INVALID_DATA = [
('abc', 0),
('abc', 2),
('abc', 4),
]


class TestAudioop(unittest.TestCase):

Expand Down Expand Up @@ -168,6 +174,33 @@ def test_negativelen(self):
self.assertRaises(audioop.error,
audioop.findmax, ''.join(chr(x) for x in range(256)), -2392392)

def test_issue7673(self):
state = None
for data, size in INVALID_DATA:
size2 = size
self.assertRaises(audioop.error, audioop.getsample, data, size, 0)
self.assertRaises(audioop.error, audioop.max, data, size)
self.assertRaises(audioop.error, audioop.minmax, data, size)
self.assertRaises(audioop.error, audioop.avg, data, size)
self.assertRaises(audioop.error, audioop.rms, data, size)
self.assertRaises(audioop.error, audioop.avgpp, data, size)
self.assertRaises(audioop.error, audioop.maxpp, data, size)
self.assertRaises(audioop.error, audioop.cross, data, size)
self.assertRaises(audioop.error, audioop.mul, data, size, 1.0)
self.assertRaises(audioop.error, audioop.tomono, data, size, 0.5, 0.5)
self.assertRaises(audioop.error, audioop.tostereo, data, size, 0.5, 0.5)
self.assertRaises(audioop.error, audioop.add, data, data, size)
self.assertRaises(audioop.error, audioop.bias, data, size, 0)
self.assertRaises(audioop.error, audioop.reverse, data, size)
self.assertRaises(audioop.error, audioop.lin2lin, data, size, size2)
self.assertRaises(audioop.error, audioop.ratecv, data, size, 1, 1, 1, state)
self.assertRaises(audioop.error, audioop.lin2ulaw, data, size)
self.assertRaises(audioop.error, audioop.ulaw2lin, data, size)
self.assertRaises(audioop.error, audioop.lin2alaw, data, size)
self.assertRaises(audioop.error, audioop.alaw2lin, data, size)
self.assertRaises(audioop.error, audioop.lin2adpcm, data, size, state)
self.assertRaises(audioop.error, audioop.adpcm2lin, data, size, state)

def test_main():
run_unittest(TestAudioop)

Expand Down
5 changes: 4 additions & 1 deletion Misc/NEWS
Expand Up @@ -468,13 +468,16 @@ C-API
Library
-------

- Issue #7673: Fix security vulnerability (CVE-2010-2089) in the audioop
module, ensure that the input string length is a multiple of the frame size

- Issue #6507: Accept source strings in dis.dis(). Original patch by
Daniel Urban.

- Issue #7829: Clearly document that the dis module is exposing an
implementation detail that is not stable between Python VMs or releases.

- Issue #6589: cleanup asyncore.socket_map in case smtpd.SMTPServer constructor
- Issue #6589: cleanup asyncore.socket_map in case smtpd.SMTPServer constructor
raises an exception.

- Issue #9110: Addition of ContextDecorator to contextlib, for creating APIs
Expand Down
144 changes: 71 additions & 73 deletions Modules/audioop.c
Expand Up @@ -297,6 +297,29 @@ static int stepsizeTable[89] = {

static PyObject *AudioopError;

static int
audioop_check_size(int size)
{
if (size != 1 && size != 2 && size != 4) {
PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
return 0;
}
else
return 1;
}

static int
audioop_check_parameters(int len, int size)
{
if (!audioop_check_size(size))
return 0;
if (len % size != 0) {
PyErr_SetString(AudioopError, "not a whole number of frames");
return 0;
}
return 1;
}

static PyObject *
audioop_getsample(PyObject *self, PyObject *args)
{
Expand All @@ -306,10 +329,8 @@ audioop_getsample(PyObject *self, PyObject *args)

if ( !PyArg_ParseTuple(args, "s#in:getsample", &cp, &len, &size, &i) )
return 0;
if ( size != 1 && size != 2 && size != 4 ) {
PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
return 0;
}
if (!audioop_check_parameters(len, size))
return NULL;
if ( i < 0 || i >= len/size ) {
PyErr_SetString(AudioopError, "Index out of range");
return 0;
Expand All @@ -330,10 +351,8 @@ audioop_max(PyObject *self, PyObject *args)

if ( !PyArg_ParseTuple(args, "s#i:max", &cp, &len, &size) )
return 0;
if ( size != 1 && size != 2 && size != 4 ) {
PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
return 0;
}
if (!audioop_check_parameters(len, size))
return NULL;
for ( i=0; i<len; i+= size) {
if ( size == 1 ) val = (int)*CHARP(cp, i);
else if ( size == 2 ) val = (int)*SHORTP(cp, i);
Expand All @@ -354,10 +373,8 @@ audioop_minmax(PyObject *self, PyObject *args)

if (!PyArg_ParseTuple(args, "s#i:minmax", &cp, &len, &size))
return NULL;
if (size != 1 && size != 2 && size != 4) {
PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
if (!audioop_check_parameters(len, size))
return NULL;
}
for (i = 0; i < len; i += size) {
if (size == 1) val = (int) *CHARP(cp, i);
else if (size == 2) val = (int) *SHORTP(cp, i);
Expand All @@ -378,10 +395,8 @@ audioop_avg(PyObject *self, PyObject *args)

if ( !PyArg_ParseTuple(args, "s#i:avg", &cp, &len, &size) )
return 0;
if ( size != 1 && size != 2 && size != 4 ) {
PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
return 0;
}
if (!audioop_check_parameters(len, size))
return NULL;
for ( i=0; i<len; i+= size) {
if ( size == 1 ) val = (int)*CHARP(cp, i);
else if ( size == 2 ) val = (int)*SHORTP(cp, i);
Expand All @@ -405,10 +420,8 @@ audioop_rms(PyObject *self, PyObject *args)

if ( !PyArg_ParseTuple(args, "s#i:rms", &cp, &len, &size) )
return 0;
if ( size != 1 && size != 2 && size != 4 ) {
PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
return 0;
}
if (!audioop_check_parameters(len, size))
return NULL;
for ( i=0; i<len; i+= size) {
if ( size == 1 ) val = (int)*CHARP(cp, i);
else if ( size == 2 ) val = (int)*SHORTP(cp, i);
Expand Down Expand Up @@ -616,10 +629,8 @@ audioop_avgpp(PyObject *self, PyObject *args)

if ( !PyArg_ParseTuple(args, "s#i:avgpp", &cp, &len, &size) )
return 0;
if ( size != 1 && size != 2 && size != 4 ) {
PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
return 0;
}
if (!audioop_check_parameters(len, size))
return NULL;
/* Compute first delta value ahead. Also automatically makes us
** skip the first extreme value
*/
Expand Down Expand Up @@ -673,10 +684,8 @@ audioop_maxpp(PyObject *self, PyObject *args)

if ( !PyArg_ParseTuple(args, "s#i:maxpp", &cp, &len, &size) )
return 0;
if ( size != 1 && size != 2 && size != 4 ) {
PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
return 0;
}
if (!audioop_check_parameters(len, size))
return NULL;
/* Compute first delta value ahead. Also automatically makes us
** skip the first extreme value
*/
Expand Down Expand Up @@ -725,10 +734,8 @@ audioop_cross(PyObject *self, PyObject *args)

if ( !PyArg_ParseTuple(args, "s#i:cross", &cp, &len, &size) )
return 0;
if ( size != 1 && size != 2 && size != 4 ) {
PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
return 0;
}
if (!audioop_check_parameters(len, size))
return NULL;
ncross = -1;
prevval = 17; /* Anything <> 0,1 */
for ( i=0; i<len; i+= size) {
Expand All @@ -753,6 +760,8 @@ audioop_mul(PyObject *self, PyObject *args)

if ( !PyArg_ParseTuple(args, "s#id:mul", &cp, &len, &size, &factor ) )
return 0;
if (!audioop_check_parameters(len, size))
return NULL;

if ( size == 1 ) maxval = (double) 0x7f;
else if ( size == 2 ) maxval = (double) 0x7fff;
Expand Down Expand Up @@ -798,6 +807,12 @@ audioop_tomono(PyObject *self, PyObject *args)
return 0;
cp = pcp.buf;
len = pcp.len;
if (!audioop_check_parameters(len, size))
return NULL;
if (((len / size) & 1) != 0) {
PyErr_SetString(AudioopError, "not a whole number of frames");
return NULL;
}

if ( size == 1 ) maxval = (double) 0x7f;
else if ( size == 2 ) maxval = (double) 0x7fff;
Expand Down Expand Up @@ -845,6 +860,8 @@ audioop_tostereo(PyObject *self, PyObject *args)
if ( !PyArg_ParseTuple(args, "s#idd:tostereo",
&cp, &len, &size, &fac1, &fac2 ) )
return 0;
if (!audioop_check_parameters(len, size))
return NULL;

if ( size == 1 ) maxval = (double) 0x7f;
else if ( size == 2 ) maxval = (double) 0x7fff;
Expand Down Expand Up @@ -903,7 +920,8 @@ audioop_add(PyObject *self, PyObject *args)
if ( !PyArg_ParseTuple(args, "s#s#i:add",
&cp1, &len1, &cp2, &len2, &size ) )
return 0;

if (!audioop_check_parameters(len1, size))
return NULL;
if ( len1 != len2 ) {
PyErr_SetString(AudioopError, "Lengths should be the same");
return 0;
Expand Down Expand Up @@ -958,10 +976,8 @@ audioop_bias(PyObject *self, PyObject *args)
&cp, &len, &size , &bias) )
return 0;

if ( size != 1 && size != 2 && size != 4) {
PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
return 0;
}
if (!audioop_check_parameters(len, size))
return NULL;

rv = PyBytes_FromStringAndSize(NULL, len);
if ( rv == 0 )
Expand Down Expand Up @@ -994,10 +1010,8 @@ audioop_reverse(PyObject *self, PyObject *args)
&cp, &len, &size) )
return 0;

if ( size != 1 && size != 2 && size != 4 ) {
PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
return 0;
}
if (!audioop_check_parameters(len, size))
return NULL;

rv = PyBytes_FromStringAndSize(NULL, len);
if ( rv == 0 )
Expand Down Expand Up @@ -1031,11 +1045,10 @@ audioop_lin2lin(PyObject *self, PyObject *args)
&cp, &len, &size, &size2) )
return 0;

if ( (size != 1 && size != 2 && size != 4) ||
(size2 != 1 && size2 != 2 && size2 != 4)) {
PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
return 0;
}
if (!audioop_check_parameters(len, size))
return NULL;
if (!audioop_check_size(size2))
return NULL;

if (len/size > PY_SSIZE_T_MAX/size2) {
PyErr_SetString(PyExc_MemoryError,
Expand Down Expand Up @@ -1086,10 +1099,8 @@ audioop_ratecv(PyObject *self, PyObject *args)
&nchannels, &inrate, &outrate, &state,
&weightA, &weightB))
return NULL;
if (size != 1 && size != 2 && size != 4) {
PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
if (!audioop_check_size(size))
return NULL;
}
if (nchannels < 1) {
PyErr_SetString(AudioopError, "# of channels should be >= 1");
return NULL;
Expand Down Expand Up @@ -1265,10 +1276,8 @@ audioop_lin2ulaw(PyObject *self, PyObject *args)
&cp, &len, &size) )
return 0 ;

if ( size != 1 && size != 2 && size != 4) {
PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
return 0;
}
if (!audioop_check_parameters(len, size))
return NULL;

rv = PyBytes_FromStringAndSize(NULL, len/size);
if ( rv == 0 )
Expand Down Expand Up @@ -1299,10 +1308,8 @@ audioop_ulaw2lin(PyObject *self, PyObject *args)
&cp, &len, &size) )
return 0;

if ( size != 1 && size != 2 && size != 4) {
PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
return 0;
}
if (!audioop_check_parameters(len, size))
return NULL;

if (len > PY_SSIZE_T_MAX/size) {
PyErr_SetString(PyExc_MemoryError,
Expand Down Expand Up @@ -1338,10 +1345,8 @@ audioop_lin2alaw(PyObject *self, PyObject *args)
&cp, &len, &size) )
return 0;

if ( size != 1 && size != 2 && size != 4) {
PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
return 0;
}
if (!audioop_check_parameters(len, size))
return NULL;

rv = PyBytes_FromStringAndSize(NULL, len/size);
if ( rv == 0 )
Expand Down Expand Up @@ -1372,10 +1377,8 @@ audioop_alaw2lin(PyObject *self, PyObject *args)
&cp, &len, &size) )
return 0;

if ( size != 1 && size != 2 && size != 4) {
PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
return 0;
}
if (!audioop_check_parameters(len, size))
return NULL;

if (len > PY_SSIZE_T_MAX/size) {
PyErr_SetString(PyExc_MemoryError,
Expand Down Expand Up @@ -1413,11 +1416,8 @@ audioop_lin2adpcm(PyObject *self, PyObject *args)
&cp, &len, &size, &state) )
return 0;


if ( size != 1 && size != 2 && size != 4) {
PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
return 0;
}
if (!audioop_check_parameters(len, size))
return NULL;

str = PyBytes_FromStringAndSize(NULL, len/(size*2));
if ( str == 0 )
Expand Down Expand Up @@ -1522,10 +1522,8 @@ audioop_adpcm2lin(PyObject *self, PyObject *args)
&cp, &len, &size, &state) )
return 0;

if ( size != 1 && size != 2 && size != 4) {
PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
return 0;
}
if (!audioop_check_parameters(len, size))
return NULL;

/* Decode state, should have (value, step) */
if ( state == Py_None ) {
Expand Down

0 comments on commit bc5c54b

Please sign in to comment.