[Python-checkins] cpython (merge 3.4 -> 3.5): Issue #24456: Fixed possible buffer over-read in adpcm2lin() and lin2adpcm()

serhiy.storchaka python-checkins at python.org
Sun Jun 28 16:56:58 CEST 2015


https://hg.python.org/cpython/rev/3039cb5b673c
changeset:   96704:3039cb5b673c
branch:      3.5
parent:      96699:20aa7083057e
parent:      96703:fd17e168b59f
user:        Serhiy Storchaka <storchaka at gmail.com>
date:        Sun Jun 28 17:55:33 2015 +0300
summary:
  Issue #24456: Fixed possible buffer over-read in adpcm2lin() and lin2adpcm()
functions of the audioop module.

files:
  Lib/test/test_audioop.py |  10 +++++++
  Misc/NEWS                |   3 ++
  Modules/audioop.c        |  39 ++++++++++++++++++---------
  3 files changed, 39 insertions(+), 13 deletions(-)


diff --git a/Lib/test/test_audioop.py b/Lib/test/test_audioop.py
--- a/Lib/test/test_audioop.py
+++ b/Lib/test/test_audioop.py
@@ -273,6 +273,16 @@
         # 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),
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -25,6 +25,9 @@
 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
   keyword arguments called "func" and "self".  Patch by Martin Panter.
 
diff --git a/Modules/audioop.c b/Modules/audioop.c
--- a/Modules/audioop.c
+++ b/Modules/audioop.c
@@ -1627,22 +1627,29 @@
     if (!audioop_check_parameters(fragment->len, width))
         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) */
     if ( state == Py_None ) {
         /* First time, it seems. Set defaults */
         valpred = 0;
         index = 0;
-    } else if (!PyTuple_Check(state)) {
+    }
+    else if (!PyTuple_Check(state)) {
         PyErr_SetString(PyExc_TypeError, "state must be a tuple or None");
-        goto exit;
-    } else if (!PyArg_ParseTuple(state, "ii", &valpred, &index)) {
-        goto exit;
+        return NULL;
     }
+    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];
     bufferstep = 1;
@@ -1718,8 +1725,6 @@
         bufferstep = !bufferstep;
     }
     rv = Py_BuildValue("(O(ii))", str, valpred, index);
-
-  exit:
     Py_DECREF(str);
     return rv;
 }
@@ -1755,11 +1760,19 @@
         /* First time, it seems. Set defaults */
         valpred = 0;
         index = 0;
-    } else if (!PyTuple_Check(state)) {
+    }
+    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))
+    }
+    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;
+    }
 
     if (fragment->len > (PY_SSIZE_T_MAX/2)/width) {
         PyErr_SetString(PyExc_MemoryError,

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list