]> granicus.if.org Git - python/commitdiff
Issue #29028: Fixed possible use-after-free bugs in the subscription of the
authorSerhiy Storchaka <storchaka@gmail.com>
Wed, 1 Feb 2017 20:47:44 +0000 (22:47 +0200)
committerSerhiy Storchaka <storchaka@gmail.com>
Wed, 1 Feb 2017 20:47:44 +0000 (22:47 +0200)
buffer object with custom index object.

Misc/NEWS
Objects/bufferobject.c

index 55aa23b63ece5464a7a258b0fe9c58b353588c6d..a3f6aa160994d7ea197e001c943be0e360deb8b3 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@ What's New in Python 2.7.14?
 Core and Builtins
 -----------------
 
+- Issue #29028: Fixed possible use-after-free bugs in the subscription of the
+  buffer object with custom index object.
+
 - Issue #29145: Fix overflow checks in string, bytearray and unicode.
   Patch by jan matejek and Xiang Zhang.
 
index bcfab71787e322f6d6db824ac91161381ec1d39b..65857bf0b396a14895be806feee11cd4b4d50b28 100644 (file)
@@ -462,12 +462,8 @@ buffer_repeat(PyBufferObject *self, Py_ssize_t count)
 }
 
 static PyObject *
-buffer_item(PyBufferObject *self, Py_ssize_t idx)
+buffer_item_impl(void *ptr, Py_ssize_t size, Py_ssize_t idx)
 {
-    void *ptr;
-    Py_ssize_t size;
-    if (!get_buf(self, &ptr, &size, ANY_BUFFER))
-        return NULL;
     if ( idx < 0 || idx >= size ) {
         PyErr_SetString(PyExc_IndexError, "buffer index out of range");
         return NULL;
@@ -475,6 +471,16 @@ buffer_item(PyBufferObject *self, Py_ssize_t idx)
     return PyString_FromStringAndSize((char *)ptr + idx, 1);
 }
 
+static PyObject *
+buffer_item(PyBufferObject *self, Py_ssize_t idx)
+{
+    void *ptr;
+    Py_ssize_t size;
+    if (!get_buf(self, &ptr, &size, ANY_BUFFER))
+        return NULL;
+    return buffer_item_impl(ptr, size, idx);
+}
+
 static PyObject *
 buffer_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right)
 {
@@ -500,24 +506,27 @@ buffer_subscript(PyBufferObject *self, PyObject *item)
     void *p;
     Py_ssize_t size;
 
-    if (!get_buf(self, &p, &size, ANY_BUFFER))
-        return NULL;
     if (PyIndex_Check(item)) {
         Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
         if (i == -1 && PyErr_Occurred())
             return NULL;
-        if (i < 0)
+        if (!get_buf(self, &p, &size, ANY_BUFFER))
+            return NULL;
+
+        if (i < 0) {
             i += size;
-        return buffer_item(self, i);
+        }
+        return buffer_item_impl(p, size, i);
     }
     else if (PySlice_Check(item)) {
         Py_ssize_t start, stop, step, slicelength, cur, i;
 
-        if (PySlice_GetIndicesEx((PySliceObject*)item, size,
-                         &start, &stop, &step, &slicelength) < 0) {
+        if (_PySlice_Unpack(item, &start, &stop, &step) < 0)
+            return NULL;
+        if (!get_buf(self, &p, &size, ANY_BUFFER))
             return NULL;
-        }
 
+        slicelength = _PySlice_AdjustIndices(size, &start, &stop, step);
         if (slicelength <= 0)
             return PyString_FromStringAndSize("", 0);
         else if (step == 1)
@@ -550,22 +559,12 @@ buffer_subscript(PyBufferObject *self, PyObject *item)
 }
 
 static int
-buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
+buffer_ass_item_impl(void *ptr1, Py_ssize_t size, Py_ssize_t idx, PyObject *other)
 {
     PyBufferProcs *pb;
-    void *ptr1, *ptr2;
-    Py_ssize_t size;
+    void *ptr2;
     Py_ssize_t count;
 
-    if ( self->b_readonly ) {
-        PyErr_SetString(PyExc_TypeError,
-                        "buffer is read-only");
-        return -1;
-    }
-
-    if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
-        return -1;
-
     if (idx < 0 || idx >= size) {
         PyErr_SetString(PyExc_IndexError,
                         "buffer assignment index out of range");
@@ -600,6 +599,23 @@ buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
     return 0;
 }
 
+static int
+buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
+{
+    void *ptr1;
+    Py_ssize_t size;
+
+    if ( self->b_readonly ) {
+        PyErr_SetString(PyExc_TypeError,
+                        "buffer is read-only");
+        return -1;
+    }
+
+    if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
+        return -1;
+    return buffer_ass_item_impl(ptr1, size, idx, other);
+}
+
 static int
 buffer_ass_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right, PyObject *other)
 {
@@ -687,23 +703,26 @@ buffer_ass_subscript(PyBufferObject *self, PyObject *item, PyObject *value)
                         "single-segment buffer object expected");
         return -1;
     }
-    if (!get_buf(self, &ptr1, &selfsize, ANY_BUFFER))
-        return -1;
     if (PyIndex_Check(item)) {
         Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
         if (i == -1 && PyErr_Occurred())
             return -1;
+        if (!get_buf(self, &ptr1, &selfsize, ANY_BUFFER))
+            return -1;
+
         if (i < 0)
             i += selfsize;
-        return buffer_ass_item(self, i, value);
+        return buffer_ass_item_impl(ptr1, selfsize, i, value);
     }
     else if (PySlice_Check(item)) {
         Py_ssize_t start, stop, step, slicelength;
 
-        if (PySlice_GetIndicesEx((PySliceObject *)item, selfsize,
-                        &start, &stop, &step, &slicelength) < 0)
+        if (_PySlice_Unpack(item, &start, &stop, &step) < 0)
+            return -1;
+        if (!get_buf(self, &ptr1, &selfsize, ANY_BUFFER))
             return -1;
 
+        slicelength = _PySlice_AdjustIndices(selfsize, &start, &stop, step);
         if ((othersize = (*pb->bf_getreadbuffer)(value, 0, &ptr2)) < 0)
             return -1;