@@ -201,6 +201,11 @@ PyTypeObject _PyManagedBuffer_Type = {
201201 return -1; \
202202 }
203203
204+ /* See gh-92888. These macros signal that we need to check the memoryview
205+ again due to possible read after frees. */
206+ #define CHECK_RELEASED_AGAIN (mv ) CHECK_RELEASED(mv)
207+ #define CHECK_RELEASED_INT_AGAIN (mv ) CHECK_RELEASED_INT(mv)
208+
204209#define CHECK_LIST_OR_TUPLE (v ) \
205210 if (!PyList_Check(v) && !PyTuple_Check(v)) { \
206211 PyErr_SetString(PyExc_TypeError, \
@@ -389,8 +394,9 @@ copy_rec(const Py_ssize_t *shape, Py_ssize_t ndim, Py_ssize_t itemsize,
389394
390395/* Faster copying of one-dimensional arrays. */
391396static int
392- copy_single (Py_buffer * dest , Py_buffer * src )
397+ copy_single (PyMemoryViewObject * self , const Py_buffer * dest , const Py_buffer * src )
393398{
399+ CHECK_RELEASED_INT_AGAIN (self );
394400 char * mem = NULL ;
395401
396402 assert (dest -> ndim == 1 );
@@ -1685,7 +1691,7 @@ pylong_as_zu(PyObject *item)
16851691 module syntax. This function is very sensitive to small changes. With this
16861692 layout gcc automatically generates a fast jump table. */
16871693static inline PyObject *
1688- unpack_single (const char * ptr , const char * fmt )
1694+ unpack_single (PyMemoryViewObject * self , const char * ptr , const char * fmt )
16891695{
16901696 unsigned long long llu ;
16911697 unsigned long lu ;
@@ -1697,6 +1703,8 @@ unpack_single(const char *ptr, const char *fmt)
16971703 unsigned char uc ;
16981704 void * p ;
16991705
1706+ CHECK_RELEASED_AGAIN (self );
1707+
17001708 switch (fmt [0 ]) {
17011709
17021710 /* signed integers and fast path for 'B' */
@@ -1775,7 +1783,7 @@ unpack_single(const char *ptr, const char *fmt)
17751783/* Pack a single item. 'fmt' can be any native format character in
17761784 struct module syntax. */
17771785static int
1778- pack_single (char * ptr , PyObject * item , const char * fmt )
1786+ pack_single (PyMemoryViewObject * self , char * ptr , PyObject * item , const char * fmt )
17791787{
17801788 unsigned long long llu ;
17811789 unsigned long lu ;
@@ -1792,6 +1800,7 @@ pack_single(char *ptr, PyObject *item, const char *fmt)
17921800 ld = pylong_as_ld (item );
17931801 if (ld == -1 && PyErr_Occurred ())
17941802 goto err_occurred ;
1803+ CHECK_RELEASED_INT_AGAIN (self );
17951804 switch (fmt [0 ]) {
17961805 case 'b' :
17971806 if (ld < SCHAR_MIN || ld > SCHAR_MAX ) goto err_range ;
@@ -1812,6 +1821,7 @@ pack_single(char *ptr, PyObject *item, const char *fmt)
18121821 lu = pylong_as_lu (item );
18131822 if (lu == (unsigned long )-1 && PyErr_Occurred ())
18141823 goto err_occurred ;
1824+ CHECK_RELEASED_INT_AGAIN (self );
18151825 switch (fmt [0 ]) {
18161826 case 'B' :
18171827 if (lu > UCHAR_MAX ) goto err_range ;
@@ -1832,12 +1842,14 @@ pack_single(char *ptr, PyObject *item, const char *fmt)
18321842 lld = pylong_as_lld (item );
18331843 if (lld == -1 && PyErr_Occurred ())
18341844 goto err_occurred ;
1845+ CHECK_RELEASED_INT_AGAIN (self );
18351846 PACK_SINGLE (ptr , lld , long long );
18361847 break ;
18371848 case 'Q' :
18381849 llu = pylong_as_llu (item );
18391850 if (llu == (unsigned long long )-1 && PyErr_Occurred ())
18401851 goto err_occurred ;
1852+ CHECK_RELEASED_INT_AGAIN (self );
18411853 PACK_SINGLE (ptr , llu , unsigned long long);
18421854 break ;
18431855
@@ -1846,12 +1858,14 @@ pack_single(char *ptr, PyObject *item, const char *fmt)
18461858 zd = pylong_as_zd (item );
18471859 if (zd == -1 && PyErr_Occurred ())
18481860 goto err_occurred ;
1861+ CHECK_RELEASED_INT_AGAIN (self );
18491862 PACK_SINGLE (ptr , zd , Py_ssize_t );
18501863 break ;
18511864 case 'N' :
18521865 zu = pylong_as_zu (item );
18531866 if (zu == (size_t )-1 && PyErr_Occurred ())
18541867 goto err_occurred ;
1868+ CHECK_RELEASED_INT_AGAIN (self );
18551869 PACK_SINGLE (ptr , zu , size_t );
18561870 break ;
18571871
@@ -1860,6 +1874,7 @@ pack_single(char *ptr, PyObject *item, const char *fmt)
18601874 d = PyFloat_AsDouble (item );
18611875 if (d == -1.0 && PyErr_Occurred ())
18621876 goto err_occurred ;
1877+ CHECK_RELEASED_INT_AGAIN (self );
18631878 if (fmt [0 ] == 'f' ) {
18641879 PACK_SINGLE (ptr , d , float );
18651880 }
@@ -1873,6 +1888,7 @@ pack_single(char *ptr, PyObject *item, const char *fmt)
18731888 ld = PyObject_IsTrue (item );
18741889 if (ld < 0 )
18751890 return -1 ; /* preserve original error */
1891+ CHECK_RELEASED_INT_AGAIN (self );
18761892 PACK_SINGLE (ptr , ld , _Bool );
18771893 break ;
18781894
@@ -1890,6 +1906,7 @@ pack_single(char *ptr, PyObject *item, const char *fmt)
18901906 p = PyLong_AsVoidPtr (item );
18911907 if (p == NULL && PyErr_Occurred ())
18921908 goto err_occurred ;
1909+ CHECK_RELEASED_INT_AGAIN (self );
18931910 PACK_SINGLE (ptr , p , void * );
18941911 break ;
18951912
@@ -2056,7 +2073,7 @@ adjust_fmt(const Py_buffer *view)
20562073
20572074/* Base case for multi-dimensional unpacking. Assumption: ndim == 1. */
20582075static PyObject *
2059- tolist_base (const char * ptr , const Py_ssize_t * shape ,
2076+ tolist_base (PyMemoryViewObject * self , const char * ptr , const Py_ssize_t * shape ,
20602077 const Py_ssize_t * strides , const Py_ssize_t * suboffsets ,
20612078 const char * fmt )
20622079{
@@ -2069,7 +2086,7 @@ tolist_base(const char *ptr, const Py_ssize_t *shape,
20692086
20702087 for (i = 0 ; i < shape [0 ]; ptr += strides [0 ], i ++ ) {
20712088 const char * xptr = ADJUST_PTR (ptr , suboffsets , 0 );
2072- item = unpack_single (xptr , fmt );
2089+ item = unpack_single (self , xptr , fmt );
20732090 if (item == NULL ) {
20742091 Py_DECREF (lst );
20752092 return NULL ;
@@ -2083,7 +2100,7 @@ tolist_base(const char *ptr, const Py_ssize_t *shape,
20832100/* Unpack a multi-dimensional array into a nested list.
20842101 Assumption: ndim >= 1. */
20852102static PyObject *
2086- tolist_rec (const char * ptr , Py_ssize_t ndim , const Py_ssize_t * shape ,
2103+ tolist_rec (PyMemoryViewObject * self , const char * ptr , Py_ssize_t ndim , const Py_ssize_t * shape ,
20872104 const Py_ssize_t * strides , const Py_ssize_t * suboffsets ,
20882105 const char * fmt )
20892106{
@@ -2095,15 +2112,15 @@ tolist_rec(const char *ptr, Py_ssize_t ndim, const Py_ssize_t *shape,
20952112 assert (strides != NULL );
20962113
20972114 if (ndim == 1 )
2098- return tolist_base (ptr , shape , strides , suboffsets , fmt );
2115+ return tolist_base (self , ptr , shape , strides , suboffsets , fmt );
20992116
21002117 lst = PyList_New (shape [0 ]);
21012118 if (lst == NULL )
21022119 return NULL ;
21032120
21042121 for (i = 0 ; i < shape [0 ]; ptr += strides [0 ], i ++ ) {
21052122 const char * xptr = ADJUST_PTR (ptr , suboffsets , 0 );
2106- item = tolist_rec (xptr , ndim - 1 , shape + 1 ,
2123+ item = tolist_rec (self , xptr , ndim - 1 , shape + 1 ,
21072124 strides + 1 , suboffsets ? suboffsets + 1 : NULL ,
21082125 fmt );
21092126 if (item == NULL ) {
@@ -2137,15 +2154,15 @@ memoryview_tolist_impl(PyMemoryViewObject *self)
21372154 if (fmt == NULL )
21382155 return NULL ;
21392156 if (view -> ndim == 0 ) {
2140- return unpack_single (view -> buf , fmt );
2157+ return unpack_single (self , view -> buf , fmt );
21412158 }
21422159 else if (view -> ndim == 1 ) {
2143- return tolist_base (view -> buf , view -> shape ,
2160+ return tolist_base (self , view -> buf , view -> shape ,
21442161 view -> strides , view -> suboffsets ,
21452162 fmt );
21462163 }
21472164 else {
2148- return tolist_rec (view -> buf , view -> ndim , view -> shape ,
2165+ return tolist_rec (self , view -> buf , view -> ndim , view -> shape ,
21492166 view -> strides , view -> suboffsets ,
21502167 fmt );
21512168 }
@@ -2353,7 +2370,7 @@ memory_item(PyMemoryViewObject *self, Py_ssize_t index)
23532370 char * ptr = ptr_from_index (view , index );
23542371 if (ptr == NULL )
23552372 return NULL ;
2356- return unpack_single (ptr , fmt );
2373+ return unpack_single (self , ptr , fmt );
23572374 }
23582375
23592376 PyErr_SetString (PyExc_NotImplementedError ,
@@ -2384,7 +2401,7 @@ memory_item_multi(PyMemoryViewObject *self, PyObject *tup)
23842401 ptr = ptr_from_tuple (view , tup );
23852402 if (ptr == NULL )
23862403 return NULL ;
2387- return unpack_single (ptr , fmt );
2404+ return unpack_single (self , ptr , fmt );
23882405}
23892406
23902407static inline int
@@ -2471,7 +2488,7 @@ memory_subscript(PyMemoryViewObject *self, PyObject *key)
24712488 const char * fmt = adjust_fmt (view );
24722489 if (fmt == NULL )
24732490 return NULL ;
2474- return unpack_single (view -> buf , fmt );
2491+ return unpack_single (self , view -> buf , fmt );
24752492 }
24762493 else if (key == Py_Ellipsis ) {
24772494 Py_INCREF (self );
@@ -2546,7 +2563,7 @@ memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
25462563 if (key == Py_Ellipsis ||
25472564 (PyTuple_Check (key ) && PyTuple_GET_SIZE (key )== 0 )) {
25482565 ptr = (char * )view -> buf ;
2549- return pack_single (ptr , value , fmt );
2566+ return pack_single (self , ptr , value , fmt );
25502567 }
25512568 else {
25522569 PyErr_SetString (PyExc_TypeError ,
@@ -2568,7 +2585,7 @@ memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
25682585 ptr = ptr_from_index (view , index );
25692586 if (ptr == NULL )
25702587 return -1 ;
2571- return pack_single (ptr , value , fmt );
2588+ return pack_single (self , ptr , value , fmt );
25722589 }
25732590 /* one-dimensional: fast path */
25742591 if (PySlice_Check (key ) && view -> ndim == 1 ) {
@@ -2591,7 +2608,7 @@ memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
25912608 goto end_block ;
25922609 dest .len = dest .shape [0 ] * dest .itemsize ;
25932610
2594- ret = copy_single (& dest , & src );
2611+ ret = copy_single (self , & dest , & src );
25952612
25962613 end_block :
25972614 PyBuffer_Release (& src );
@@ -2607,7 +2624,7 @@ memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
26072624 ptr = ptr_from_tuple (view , key );
26082625 if (ptr == NULL )
26092626 return -1 ;
2610- return pack_single (ptr , value , fmt );
2627+ return pack_single (self , ptr , value , fmt );
26112628 }
26122629 if (PySlice_Check (key ) || is_multislice (key )) {
26132630 /* Call memory_subscript() to produce a sliced lvalue, then copy
@@ -3208,7 +3225,7 @@ memoryiter_next(memoryiterobject *it)
32083225 if (ptr == NULL ) {
32093226 return NULL ;
32103227 }
3211- return unpack_single (ptr , it -> it_fmt );
3228+ return unpack_single (seq , ptr , it -> it_fmt );
32123229 }
32133230
32143231 it -> it_seq = NULL ;
0 commit comments