gh-92888: Fix memoryview bad `__index__` use after free (GH-92946) · python/cpython@2eff55c

GitHub

@@ -193,6 +193,11 @@ PyTypeObject _PyManagedBuffer_Type = {

193193 return -1; \

194194 }

195195196+/* See gh-92888. These macros signal that we need to check the memoryview

197+ again due to possible read after frees. */

198+#defineCHECK_RELEASED_AGAIN(mv) CHECK_RELEASED(mv)

199+#defineCHECK_RELEASED_INT_AGAIN(mv) CHECK_RELEASED_INT(mv)

200+196201#defineCHECK_LIST_OR_TUPLE(v) \

197202 if (!PyList_Check(v) && !PyTuple_Check(v)) { \

198203 PyErr_SetString(PyExc_TypeError, \

@@ -381,8 +386,9 @@ copy_rec(const Py_ssize_t *shape, Py_ssize_t ndim, Py_ssize_t itemsize,

381386382387/* Faster copying of one-dimensional arrays. */

383388staticint

384-copy_single(constPy_buffer*dest, constPy_buffer*src)

389+copy_single(PyMemoryViewObject*self, constPy_buffer*dest, constPy_buffer*src)

385390{

391+CHECK_RELEASED_INT_AGAIN(self);

386392char*mem=NULL;

387393388394assert(dest->ndim==1);

@@ -1677,7 +1683,7 @@ pylong_as_zu(PyObject *item)

16771683 module syntax. This function is very sensitive to small changes. With this

16781684 layout gcc automatically generates a fast jump table. */

16791685staticinlinePyObject*

1680-unpack_single(constchar*ptr, constchar*fmt)

1686+unpack_single(PyMemoryViewObject*self, constchar*ptr, constchar*fmt)

16811687{

16821688unsigned long longllu;

16831689unsigned longlu;

@@ -1689,6 +1695,8 @@ unpack_single(const char *ptr, const char *fmt)

16891695unsigned charuc;

16901696void*p;

169116971698+CHECK_RELEASED_AGAIN(self);

1699+16921700switch (fmt[0]) {

1693170116941702/* signed integers and fast path for 'B' */

@@ -1767,7 +1775,7 @@ unpack_single(const char *ptr, const char *fmt)

17671775/* Pack a single item. 'fmt' can be any native format character in

17681776 struct module syntax. */

17691777staticint

1770-pack_single(char*ptr, PyObject*item, constchar*fmt)

1778+pack_single(PyMemoryViewObject*self, char*ptr, PyObject*item, constchar*fmt)

17711779{

17721780unsigned long longllu;

17731781unsigned longlu;

@@ -1784,6 +1792,7 @@ pack_single(char *ptr, PyObject *item, const char *fmt)

17841792ld=pylong_as_ld(item);

17851793if (ld==-1&&PyErr_Occurred())

17861794 goto err_occurred;

1795+CHECK_RELEASED_INT_AGAIN(self);

17871796switch (fmt[0]) {

17881797case'b':

17891798if (ld<SCHAR_MIN||ld>SCHAR_MAX) goto err_range;

@@ -1804,6 +1813,7 @@ pack_single(char *ptr, PyObject *item, const char *fmt)

18041813lu=pylong_as_lu(item);

18051814if (lu== (unsigned long)-1&&PyErr_Occurred())

18061815 goto err_occurred;

1816+CHECK_RELEASED_INT_AGAIN(self);

18071817switch (fmt[0]) {

18081818case'B':

18091819if (lu>UCHAR_MAX) goto err_range;

@@ -1824,12 +1834,14 @@ pack_single(char *ptr, PyObject *item, const char *fmt)

18241834lld=pylong_as_lld(item);

18251835if (lld==-1&&PyErr_Occurred())

18261836 goto err_occurred;

1837+CHECK_RELEASED_INT_AGAIN(self);

18271838PACK_SINGLE(ptr, lld, longlong);

18281839break;

18291840case'Q':

18301841llu=pylong_as_llu(item);

18311842if (llu== (unsigned long long)-1&&PyErr_Occurred())

18321843 goto err_occurred;

1844+CHECK_RELEASED_INT_AGAIN(self);

18331845PACK_SINGLE(ptr, llu, unsignedlong long);

18341846break;

18351847@@ -1838,12 +1850,14 @@ pack_single(char *ptr, PyObject *item, const char *fmt)

18381850zd=pylong_as_zd(item);

18391851if (zd==-1&&PyErr_Occurred())

18401852 goto err_occurred;

1853+CHECK_RELEASED_INT_AGAIN(self);

18411854PACK_SINGLE(ptr, zd, Py_ssize_t);

18421855break;

18431856case'N':

18441857zu=pylong_as_zu(item);

18451858if (zu== (size_t)-1&&PyErr_Occurred())

18461859 goto err_occurred;

1860+CHECK_RELEASED_INT_AGAIN(self);

18471861PACK_SINGLE(ptr, zu, size_t);

18481862break;

18491863@@ -1852,6 +1866,7 @@ pack_single(char *ptr, PyObject *item, const char *fmt)

18521866d=PyFloat_AsDouble(item);

18531867if (d==-1.0&&PyErr_Occurred())

18541868 goto err_occurred;

1869+CHECK_RELEASED_INT_AGAIN(self);

18551870if (fmt[0] =='f') {

18561871PACK_SINGLE(ptr, d, float);

18571872 }

@@ -1865,6 +1880,7 @@ pack_single(char *ptr, PyObject *item, const char *fmt)

18651880ld=PyObject_IsTrue(item);

18661881if (ld<0)

18671882return-1; /* preserve original error */

1883+CHECK_RELEASED_INT_AGAIN(self);

18681884PACK_SINGLE(ptr, ld, _Bool);

18691885break;

18701886@@ -1882,6 +1898,7 @@ pack_single(char *ptr, PyObject *item, const char *fmt)

18821898p=PyLong_AsVoidPtr(item);

18831899if (p==NULL&&PyErr_Occurred())

18841900 goto err_occurred;

1901+CHECK_RELEASED_INT_AGAIN(self);

18851902PACK_SINGLE(ptr, p, void*);

18861903break;

18871904@@ -2048,7 +2065,7 @@ adjust_fmt(const Py_buffer *view)

2048206520492066/* Base case for multi-dimensional unpacking. Assumption: ndim == 1. */

20502067staticPyObject*

2051-tolist_base(constchar*ptr, constPy_ssize_t*shape,

2068+tolist_base(PyMemoryViewObject*self, constchar*ptr, constPy_ssize_t*shape,

20522069constPy_ssize_t*strides, constPy_ssize_t*suboffsets,

20532070constchar*fmt)

20542071{

@@ -2061,7 +2078,7 @@ tolist_base(const char *ptr, const Py_ssize_t *shape,

2061207820622079for (i=0; i<shape[0]; ptr+=strides[0], i++) {

20632080constchar*xptr=ADJUST_PTR(ptr, suboffsets, 0);

2064-item=unpack_single(xptr, fmt);

2081+item=unpack_single(self, xptr, fmt);

20652082if (item==NULL) {

20662083Py_DECREF(lst);

20672084returnNULL;

@@ -2075,7 +2092,7 @@ tolist_base(const char *ptr, const Py_ssize_t *shape,

20752092/* Unpack a multi-dimensional array into a nested list.

20762093 Assumption: ndim >= 1. */

20772094staticPyObject*

2078-tolist_rec(constchar*ptr, Py_ssize_tndim, constPy_ssize_t*shape,

2095+tolist_rec(PyMemoryViewObject*self, constchar*ptr, Py_ssize_tndim, constPy_ssize_t*shape,

20792096constPy_ssize_t*strides, constPy_ssize_t*suboffsets,

20802097constchar*fmt)

20812098{

@@ -2087,15 +2104,15 @@ tolist_rec(const char *ptr, Py_ssize_t ndim, const Py_ssize_t *shape,

20872104assert(strides!=NULL);

2088210520892106if (ndim==1)

2090-returntolist_base(ptr, shape, strides, suboffsets, fmt);

2107+returntolist_base(self, ptr, shape, strides, suboffsets, fmt);

2091210820922109lst=PyList_New(shape[0]);

20932110if (lst==NULL)

20942111returnNULL;

2095211220962113for (i=0; i<shape[0]; ptr+=strides[0], i++) {

20972114constchar*xptr=ADJUST_PTR(ptr, suboffsets, 0);

2098-item=tolist_rec(xptr, ndim-1, shape+1,

2115+item=tolist_rec(self, xptr, ndim-1, shape+1,

20992116strides+1, suboffsets ? suboffsets+1 : NULL,

21002117fmt);

21012118if (item==NULL) {

@@ -2129,15 +2146,15 @@ memoryview_tolist_impl(PyMemoryViewObject *self)

21292146if (fmt==NULL)

21302147returnNULL;

21312148if (view->ndim==0) {

2132-returnunpack_single(view->buf, fmt);

2149+returnunpack_single(self, view->buf, fmt);

21332150 }

21342151elseif (view->ndim==1) {

2135-returntolist_base(view->buf, view->shape,

2152+returntolist_base(self, view->buf, view->shape,

21362153view->strides, view->suboffsets,

21372154fmt);

21382155 }

21392156else {

2140-returntolist_rec(view->buf, view->ndim, view->shape,

2157+returntolist_rec(self, view->buf, view->ndim, view->shape,

21412158view->strides, view->suboffsets,

21422159fmt);

21432160 }

@@ -2345,7 +2362,7 @@ memory_item(PyMemoryViewObject *self, Py_ssize_t index)

23452362char*ptr=ptr_from_index(view, index);

23462363if (ptr==NULL)

23472364returnNULL;

2348-returnunpack_single(ptr, fmt);

2365+returnunpack_single(self, ptr, fmt);

23492366 }

2350236723512368PyErr_SetString(PyExc_NotImplementedError,

@@ -2376,7 +2393,7 @@ memory_item_multi(PyMemoryViewObject *self, PyObject *tup)

23762393ptr=ptr_from_tuple(view, tup);

23772394if (ptr==NULL)

23782395returnNULL;

2379-returnunpack_single(ptr, fmt);

2396+returnunpack_single(self, ptr, fmt);

23802397}

2381239823822399staticinlineint

@@ -2463,7 +2480,7 @@ memory_subscript(PyMemoryViewObject *self, PyObject *key)

24632480constchar*fmt=adjust_fmt(view);

24642481if (fmt==NULL)

24652482returnNULL;

2466-returnunpack_single(view->buf, fmt);

2483+returnunpack_single(self, view->buf, fmt);

24672484 }

24682485elseif (key==Py_Ellipsis) {

24692486Py_INCREF(self);

@@ -2538,7 +2555,7 @@ memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)

25382555if (key==Py_Ellipsis||

25392556 (PyTuple_Check(key) &&PyTuple_GET_SIZE(key)==0)) {

25402557ptr= (char*)view->buf;

2541-returnpack_single(ptr, value, fmt);

2558+returnpack_single(self, ptr, value, fmt);

25422559 }

25432560else {

25442561PyErr_SetString(PyExc_TypeError,

@@ -2560,7 +2577,7 @@ memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)

25602577ptr=ptr_from_index(view, index);

25612578if (ptr==NULL)

25622579return-1;

2563-returnpack_single(ptr, value, fmt);

2580+returnpack_single(self, ptr, value, fmt);

25642581 }

25652582/* one-dimensional: fast path */

25662583if (PySlice_Check(key) &&view->ndim==1) {

@@ -2583,7 +2600,7 @@ memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)

25832600 goto end_block;

25842601dest.len=dest.shape[0] *dest.itemsize;

258526022586-ret=copy_single(&dest, &src);

2603+ret=copy_single(self, &dest, &src);

2587260425882605end_block:

25892606PyBuffer_Release(&src);

@@ -2599,7 +2616,7 @@ memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)

25992616ptr=ptr_from_tuple(view, key);

26002617if (ptr==NULL)

26012618return-1;

2602-returnpack_single(ptr, value, fmt);

2619+returnpack_single(self, ptr, value, fmt);

26032620 }

26042621if (PySlice_Check(key) ||is_multislice(key)) {

26052622/* Call memory_subscript() to produce a sliced lvalue, then copy

@@ -3200,7 +3217,7 @@ memoryiter_next(memoryiterobject *it)

32003217if (ptr==NULL) {

32013218returnNULL;

32023219 }

3203-returnunpack_single(ptr, it->it_fmt);

3220+returnunpack_single(seq, ptr, it->it_fmt);

32043221 }

3205322232063223it->it_seq=NULL;