@@ -193,6 +193,11 @@ PyTypeObject _PyManagedBuffer_Type = {
193193 return -1; \
194194 }
195195
196+ /* See gh-92888. These macros signal that we need to check the memoryview
197+ again due to possible read after frees. */
198+ #define CHECK_RELEASED_AGAIN (mv ) CHECK_RELEASED(mv)
199+ #define CHECK_RELEASED_INT_AGAIN (mv ) CHECK_RELEASED_INT(mv)
200+
196201#define CHECK_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,
381386
382387/* Faster copying of one-dimensional arrays. */
383388static int
384- copy_single (const Py_buffer * dest , const Py_buffer * src )
389+ copy_single (PyMemoryViewObject * self , const Py_buffer * dest , const Py_buffer * src )
385390{
391+ CHECK_RELEASED_INT_AGAIN (self );
386392 char * mem = NULL ;
387393
388394 assert (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. */
16791685static inline PyObject *
1680- unpack_single (const char * ptr , const char * fmt )
1686+ unpack_single (PyMemoryViewObject * self , const char * ptr , const char * fmt )
16811687{
16821688 unsigned long long llu ;
16831689 unsigned long lu ;
@@ -1689,6 +1695,8 @@ unpack_single(const char *ptr, const char *fmt)
16891695 unsigned char uc ;
16901696 void * p ;
16911697
1698+ CHECK_RELEASED_AGAIN (self );
1699+
16921700 switch (fmt [0 ]) {
16931701
16941702 /* 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. */
17691777static int
1770- pack_single (char * ptr , PyObject * item , const char * fmt )
1778+ pack_single (PyMemoryViewObject * self , char * ptr , PyObject * item , const char * fmt )
17711779{
17721780 unsigned long long llu ;
17731781 unsigned long lu ;
@@ -1784,6 +1792,7 @@ pack_single(char *ptr, PyObject *item, const char *fmt)
17841792 ld = pylong_as_ld (item );
17851793 if (ld == -1 && PyErr_Occurred ())
17861794 goto err_occurred ;
1795+ CHECK_RELEASED_INT_AGAIN (self );
17871796 switch (fmt [0 ]) {
17881797 case 'b' :
17891798 if (ld < SCHAR_MIN || ld > SCHAR_MAX ) goto err_range ;
@@ -1804,6 +1813,7 @@ pack_single(char *ptr, PyObject *item, const char *fmt)
18041813 lu = pylong_as_lu (item );
18051814 if (lu == (unsigned long )-1 && PyErr_Occurred ())
18061815 goto err_occurred ;
1816+ CHECK_RELEASED_INT_AGAIN (self );
18071817 switch (fmt [0 ]) {
18081818 case 'B' :
18091819 if (lu > UCHAR_MAX ) goto err_range ;
@@ -1824,12 +1834,14 @@ pack_single(char *ptr, PyObject *item, const char *fmt)
18241834 lld = pylong_as_lld (item );
18251835 if (lld == -1 && PyErr_Occurred ())
18261836 goto err_occurred ;
1837+ CHECK_RELEASED_INT_AGAIN (self );
18271838 PACK_SINGLE (ptr , lld , long long );
18281839 break ;
18291840 case 'Q' :
18301841 llu = pylong_as_llu (item );
18311842 if (llu == (unsigned long long )-1 && PyErr_Occurred ())
18321843 goto err_occurred ;
1844+ CHECK_RELEASED_INT_AGAIN (self );
18331845 PACK_SINGLE (ptr , llu , unsigned long long);
18341846 break ;
18351847
@@ -1838,12 +1850,14 @@ pack_single(char *ptr, PyObject *item, const char *fmt)
18381850 zd = pylong_as_zd (item );
18391851 if (zd == -1 && PyErr_Occurred ())
18401852 goto err_occurred ;
1853+ CHECK_RELEASED_INT_AGAIN (self );
18411854 PACK_SINGLE (ptr , zd , Py_ssize_t );
18421855 break ;
18431856 case 'N' :
18441857 zu = pylong_as_zu (item );
18451858 if (zu == (size_t )-1 && PyErr_Occurred ())
18461859 goto err_occurred ;
1860+ CHECK_RELEASED_INT_AGAIN (self );
18471861 PACK_SINGLE (ptr , zu , size_t );
18481862 break ;
18491863
@@ -1852,6 +1866,7 @@ pack_single(char *ptr, PyObject *item, const char *fmt)
18521866 d = PyFloat_AsDouble (item );
18531867 if (d == -1.0 && PyErr_Occurred ())
18541868 goto err_occurred ;
1869+ CHECK_RELEASED_INT_AGAIN (self );
18551870 if (fmt [0 ] == 'f' ) {
18561871 PACK_SINGLE (ptr , d , float );
18571872 }
@@ -1865,6 +1880,7 @@ pack_single(char *ptr, PyObject *item, const char *fmt)
18651880 ld = PyObject_IsTrue (item );
18661881 if (ld < 0 )
18671882 return -1 ; /* preserve original error */
1883+ CHECK_RELEASED_INT_AGAIN (self );
18681884 PACK_SINGLE (ptr , ld , _Bool );
18691885 break ;
18701886
@@ -1882,6 +1898,7 @@ pack_single(char *ptr, PyObject *item, const char *fmt)
18821898 p = PyLong_AsVoidPtr (item );
18831899 if (p == NULL && PyErr_Occurred ())
18841900 goto err_occurred ;
1901+ CHECK_RELEASED_INT_AGAIN (self );
18851902 PACK_SINGLE (ptr , p , void * );
18861903 break ;
18871904
@@ -2048,7 +2065,7 @@ adjust_fmt(const Py_buffer *view)
20482065
20492066/* Base case for multi-dimensional unpacking. Assumption: ndim == 1. */
20502067static PyObject *
2051- tolist_base (const char * ptr , const Py_ssize_t * shape ,
2068+ tolist_base (PyMemoryViewObject * self , const char * ptr , const Py_ssize_t * shape ,
20522069 const Py_ssize_t * strides , const Py_ssize_t * suboffsets ,
20532070 const char * fmt )
20542071{
@@ -2061,7 +2078,7 @@ tolist_base(const char *ptr, const Py_ssize_t *shape,
20612078
20622079 for (i = 0 ; i < shape [0 ]; ptr += strides [0 ], i ++ ) {
20632080 const char * xptr = ADJUST_PTR (ptr , suboffsets , 0 );
2064- item = unpack_single (xptr , fmt );
2081+ item = unpack_single (self , xptr , fmt );
20652082 if (item == NULL ) {
20662083 Py_DECREF (lst );
20672084 return NULL ;
@@ -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. */
20772094static PyObject *
2078- tolist_rec (const char * ptr , Py_ssize_t ndim , const Py_ssize_t * shape ,
2095+ tolist_rec (PyMemoryViewObject * self , const char * ptr , Py_ssize_t ndim , const Py_ssize_t * shape ,
20792096 const Py_ssize_t * strides , const Py_ssize_t * suboffsets ,
20802097 const char * fmt )
20812098{
@@ -2087,15 +2104,15 @@ tolist_rec(const char *ptr, Py_ssize_t ndim, const Py_ssize_t *shape,
20872104 assert (strides != NULL );
20882105
20892106 if (ndim == 1 )
2090- return tolist_base (ptr , shape , strides , suboffsets , fmt );
2107+ return tolist_base (self , ptr , shape , strides , suboffsets , fmt );
20912108
20922109 lst = PyList_New (shape [0 ]);
20932110 if (lst == NULL )
20942111 return NULL ;
20952112
20962113 for (i = 0 ; i < shape [0 ]; ptr += strides [0 ], i ++ ) {
20972114 const char * 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 ,
20992116 strides + 1 , suboffsets ? suboffsets + 1 : NULL ,
21002117 fmt );
21012118 if (item == NULL ) {
@@ -2129,15 +2146,15 @@ memoryview_tolist_impl(PyMemoryViewObject *self)
21292146 if (fmt == NULL )
21302147 return NULL ;
21312148 if (view -> ndim == 0 ) {
2132- return unpack_single (view -> buf , fmt );
2149+ return unpack_single (self , view -> buf , fmt );
21332150 }
21342151 else if (view -> ndim == 1 ) {
2135- return tolist_base (view -> buf , view -> shape ,
2152+ return tolist_base (self , view -> buf , view -> shape ,
21362153 view -> strides , view -> suboffsets ,
21372154 fmt );
21382155 }
21392156 else {
2140- return tolist_rec (view -> buf , view -> ndim , view -> shape ,
2157+ return tolist_rec (self , view -> buf , view -> ndim , view -> shape ,
21412158 view -> strides , view -> suboffsets ,
21422159 fmt );
21432160 }
@@ -2345,7 +2362,7 @@ memory_item(PyMemoryViewObject *self, Py_ssize_t index)
23452362 char * ptr = ptr_from_index (view , index );
23462363 if (ptr == NULL )
23472364 return NULL ;
2348- return unpack_single (ptr , fmt );
2365+ return unpack_single (self , ptr , fmt );
23492366 }
23502367
23512368 PyErr_SetString (PyExc_NotImplementedError ,
@@ -2376,7 +2393,7 @@ memory_item_multi(PyMemoryViewObject *self, PyObject *tup)
23762393 ptr = ptr_from_tuple (view , tup );
23772394 if (ptr == NULL )
23782395 return NULL ;
2379- return unpack_single (ptr , fmt );
2396+ return unpack_single (self , ptr , fmt );
23802397}
23812398
23822399static inline int
@@ -2463,7 +2480,7 @@ memory_subscript(PyMemoryViewObject *self, PyObject *key)
24632480 const char * fmt = adjust_fmt (view );
24642481 if (fmt == NULL )
24652482 return NULL ;
2466- return unpack_single (view -> buf , fmt );
2483+ return unpack_single (self , view -> buf , fmt );
24672484 }
24682485 else if (key == Py_Ellipsis ) {
24692486 Py_INCREF (self );
@@ -2538,7 +2555,7 @@ memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
25382555 if (key == Py_Ellipsis ||
25392556 (PyTuple_Check (key ) && PyTuple_GET_SIZE (key )== 0 )) {
25402557 ptr = (char * )view -> buf ;
2541- return pack_single (ptr , value , fmt );
2558+ return pack_single (self , ptr , value , fmt );
25422559 }
25432560 else {
25442561 PyErr_SetString (PyExc_TypeError ,
@@ -2560,7 +2577,7 @@ memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
25602577 ptr = ptr_from_index (view , index );
25612578 if (ptr == NULL )
25622579 return -1 ;
2563- return pack_single (ptr , value , fmt );
2580+ return pack_single (self , ptr , value , fmt );
25642581 }
25652582 /* one-dimensional: fast path */
25662583 if (PySlice_Check (key ) && view -> ndim == 1 ) {
@@ -2583,7 +2600,7 @@ memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
25832600 goto end_block ;
25842601 dest .len = dest .shape [0 ] * dest .itemsize ;
25852602
2586- ret = copy_single (& dest , & src );
2603+ ret = copy_single (self , & dest , & src );
25872604
25882605 end_block :
25892606 PyBuffer_Release (& src );
@@ -2599,7 +2616,7 @@ memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
25992616 ptr = ptr_from_tuple (view , key );
26002617 if (ptr == NULL )
26012618 return -1 ;
2602- return pack_single (ptr , value , fmt );
2619+ return pack_single (self , ptr , value , fmt );
26032620 }
26042621 if (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)
32003217 if (ptr == NULL ) {
32013218 return NULL ;
32023219 }
3203- return unpack_single (ptr , it -> it_fmt );
3220+ return unpack_single (seq , ptr , it -> it_fmt );
32043221 }
32053222
32063223 it -> it_seq = NULL ;
0 commit comments