From: Serhiy Storchaka Date: Wed, 1 Feb 2017 20:47:44 +0000 (+0200) Subject: Issue #29028: Fixed possible use-after-free bugs in the subscription of the X-Git-Tag: v2.7.14rc1~287 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8e21cc3ce010990b043068f0fab13e71c827341f;p=python Issue #29028: Fixed possible use-after-free bugs in the subscription of the buffer object with custom index object. --- diff --git a/Misc/NEWS b/Misc/NEWS index 55aa23b63e..a3f6aa1609 100644 --- 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. diff --git a/Objects/bufferobject.c b/Objects/bufferobject.c index bcfab71787..65857bf0b3 100644 --- a/Objects/bufferobject.c +++ b/Objects/bufferobject.c @@ -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;