Skip to content

Commit 8e21cc3

Browse files
Issue python#29028: Fixed possible use-after-free bugs in the subscription of the
buffer object with custom index object.
1 parent dbbc9d3 commit 8e21cc3

File tree

2 files changed

+51
-29
lines changed

2 files changed

+51
-29
lines changed

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ What's New in Python 2.7.14?
1010
Core and Builtins
1111
-----------------
1212

13+
- Issue #29028: Fixed possible use-after-free bugs in the subscription of the
14+
buffer object with custom index object.
15+
1316
- Issue #29145: Fix overflow checks in string, bytearray and unicode.
1417
Patch by jan matejek and Xiang Zhang.
1518

Objects/bufferobject.c

Lines changed: 48 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -462,19 +462,25 @@ buffer_repeat(PyBufferObject *self, Py_ssize_t count)
462462
}
463463

464464
static PyObject *
465-
buffer_item(PyBufferObject *self, Py_ssize_t idx)
465+
buffer_item_impl(void *ptr, Py_ssize_t size, Py_ssize_t idx)
466466
{
467-
void *ptr;
468-
Py_ssize_t size;
469-
if (!get_buf(self, &ptr, &size, ANY_BUFFER))
470-
return NULL;
471467
if ( idx < 0 || idx >= size ) {
472468
PyErr_SetString(PyExc_IndexError, "buffer index out of range");
473469
return NULL;
474470
}
475471
return PyString_FromStringAndSize((char *)ptr + idx, 1);
476472
}
477473

474+
static PyObject *
475+
buffer_item(PyBufferObject *self, Py_ssize_t idx)
476+
{
477+
void *ptr;
478+
Py_ssize_t size;
479+
if (!get_buf(self, &ptr, &size, ANY_BUFFER))
480+
return NULL;
481+
return buffer_item_impl(ptr, size, idx);
482+
}
483+
478484
static PyObject *
479485
buffer_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right)
480486
{
@@ -500,24 +506,27 @@ buffer_subscript(PyBufferObject *self, PyObject *item)
500506
void *p;
501507
Py_ssize_t size;
502508

503-
if (!get_buf(self, &p, &size, ANY_BUFFER))
504-
return NULL;
505509
if (PyIndex_Check(item)) {
506510
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
507511
if (i == -1 && PyErr_Occurred())
508512
return NULL;
509-
if (i < 0)
513+
if (!get_buf(self, &p, &size, ANY_BUFFER))
514+
return NULL;
515+
516+
if (i < 0) {
510517
i += size;
511-
return buffer_item(self, i);
518+
}
519+
return buffer_item_impl(p, size, i);
512520
}
513521
else if (PySlice_Check(item)) {
514522
Py_ssize_t start, stop, step, slicelength, cur, i;
515523

516-
if (PySlice_GetIndicesEx((PySliceObject*)item, size,
517-
&start, &stop, &step, &slicelength) < 0) {
524+
if (_PySlice_Unpack(item, &start, &stop, &step) < 0)
525+
return NULL;
526+
if (!get_buf(self, &p, &size, ANY_BUFFER))
518527
return NULL;
519-
}
520528

529+
slicelength = _PySlice_AdjustIndices(size, &start, &stop, step);
521530
if (slicelength <= 0)
522531
return PyString_FromStringAndSize("", 0);
523532
else if (step == 1)
@@ -550,22 +559,12 @@ buffer_subscript(PyBufferObject *self, PyObject *item)
550559
}
551560

552561
static int
553-
buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
562+
buffer_ass_item_impl(void *ptr1, Py_ssize_t size, Py_ssize_t idx, PyObject *other)
554563
{
555564
PyBufferProcs *pb;
556-
void *ptr1, *ptr2;
557-
Py_ssize_t size;
565+
void *ptr2;
558566
Py_ssize_t count;
559567

560-
if ( self->b_readonly ) {
561-
PyErr_SetString(PyExc_TypeError,
562-
"buffer is read-only");
563-
return -1;
564-
}
565-
566-
if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
567-
return -1;
568-
569568
if (idx < 0 || idx >= size) {
570569
PyErr_SetString(PyExc_IndexError,
571570
"buffer assignment index out of range");
@@ -600,6 +599,23 @@ buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
600599
return 0;
601600
}
602601

602+
static int
603+
buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
604+
{
605+
void *ptr1;
606+
Py_ssize_t size;
607+
608+
if ( self->b_readonly ) {
609+
PyErr_SetString(PyExc_TypeError,
610+
"buffer is read-only");
611+
return -1;
612+
}
613+
614+
if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
615+
return -1;
616+
return buffer_ass_item_impl(ptr1, size, idx, other);
617+
}
618+
603619
static int
604620
buffer_ass_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right, PyObject *other)
605621
{
@@ -687,23 +703,26 @@ buffer_ass_subscript(PyBufferObject *self, PyObject *item, PyObject *value)
687703
"single-segment buffer object expected");
688704
return -1;
689705
}
690-
if (!get_buf(self, &ptr1, &selfsize, ANY_BUFFER))
691-
return -1;
692706
if (PyIndex_Check(item)) {
693707
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
694708
if (i == -1 && PyErr_Occurred())
695709
return -1;
710+
if (!get_buf(self, &ptr1, &selfsize, ANY_BUFFER))
711+
return -1;
712+
696713
if (i < 0)
697714
i += selfsize;
698-
return buffer_ass_item(self, i, value);
715+
return buffer_ass_item_impl(ptr1, selfsize, i, value);
699716
}
700717
else if (PySlice_Check(item)) {
701718
Py_ssize_t start, stop, step, slicelength;
702719

703-
if (PySlice_GetIndicesEx((PySliceObject *)item, selfsize,
704-
&start, &stop, &step, &slicelength) < 0)
720+
if (_PySlice_Unpack(item, &start, &stop, &step) < 0)
721+
return -1;
722+
if (!get_buf(self, &ptr1, &selfsize, ANY_BUFFER))
705723
return -1;
706724

725+
slicelength = _PySlice_AdjustIndices(selfsize, &start, &stop, step);
707726
if ((othersize = (*pb->bf_getreadbuffer)(value, 0, &ptr2)) < 0)
708727
return -1;
709728

0 commit comments

Comments
 (0)