@@ -201,6 +201,11 @@ PyTypeObject _PyManagedBuffer_Type = {
201
201
return -1; \
202
202
}
203
203
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
+
204
209
#define CHECK_LIST_OR_TUPLE (v ) \
205
210
if (!PyList_Check(v) && !PyTuple_Check(v)) { \
206
211
PyErr_SetString(PyExc_TypeError, \
@@ -389,8 +394,9 @@ copy_rec(const Py_ssize_t *shape, Py_ssize_t ndim, Py_ssize_t itemsize,
389
394
390
395
/* Faster copying of one-dimensional arrays. */
391
396
static int
392
- copy_single (Py_buffer * dest , Py_buffer * src )
397
+ copy_single (PyMemoryViewObject * self , const Py_buffer * dest , const Py_buffer * src )
393
398
{
399
+ CHECK_RELEASED_INT_AGAIN (self );
394
400
char * mem = NULL ;
395
401
396
402
assert (dest -> ndim == 1 );
@@ -1685,7 +1691,7 @@ pylong_as_zu(PyObject *item)
1685
1691
module syntax. This function is very sensitive to small changes. With this
1686
1692
layout gcc automatically generates a fast jump table. */
1687
1693
static inline PyObject *
1688
- unpack_single (const char * ptr , const char * fmt )
1694
+ unpack_single (PyMemoryViewObject * self , const char * ptr , const char * fmt )
1689
1695
{
1690
1696
unsigned long long llu ;
1691
1697
unsigned long lu ;
@@ -1697,6 +1703,8 @@ unpack_single(const char *ptr, const char *fmt)
1697
1703
unsigned char uc ;
1698
1704
void * p ;
1699
1705
1706
+ CHECK_RELEASED_AGAIN (self );
1707
+
1700
1708
switch (fmt [0 ]) {
1701
1709
1702
1710
/* signed integers and fast path for 'B' */
@@ -1775,7 +1783,7 @@ unpack_single(const char *ptr, const char *fmt)
1775
1783
/* Pack a single item. 'fmt' can be any native format character in
1776
1784
struct module syntax. */
1777
1785
static int
1778
- pack_single (char * ptr , PyObject * item , const char * fmt )
1786
+ pack_single (PyMemoryViewObject * self , char * ptr , PyObject * item , const char * fmt )
1779
1787
{
1780
1788
unsigned long long llu ;
1781
1789
unsigned long lu ;
@@ -1792,6 +1800,7 @@ pack_single(char *ptr, PyObject *item, const char *fmt)
1792
1800
ld = pylong_as_ld (item );
1793
1801
if (ld == -1 && PyErr_Occurred ())
1794
1802
goto err_occurred ;
1803
+ CHECK_RELEASED_INT_AGAIN (self );
1795
1804
switch (fmt [0 ]) {
1796
1805
case 'b' :
1797
1806
if (ld < SCHAR_MIN || ld > SCHAR_MAX ) goto err_range ;
@@ -1812,6 +1821,7 @@ pack_single(char *ptr, PyObject *item, const char *fmt)
1812
1821
lu = pylong_as_lu (item );
1813
1822
if (lu == (unsigned long )-1 && PyErr_Occurred ())
1814
1823
goto err_occurred ;
1824
+ CHECK_RELEASED_INT_AGAIN (self );
1815
1825
switch (fmt [0 ]) {
1816
1826
case 'B' :
1817
1827
if (lu > UCHAR_MAX ) goto err_range ;
@@ -1832,12 +1842,14 @@ pack_single(char *ptr, PyObject *item, const char *fmt)
1832
1842
lld = pylong_as_lld (item );
1833
1843
if (lld == -1 && PyErr_Occurred ())
1834
1844
goto err_occurred ;
1845
+ CHECK_RELEASED_INT_AGAIN (self );
1835
1846
PACK_SINGLE (ptr , lld , long long );
1836
1847
break ;
1837
1848
case 'Q' :
1838
1849
llu = pylong_as_llu (item );
1839
1850
if (llu == (unsigned long long )-1 && PyErr_Occurred ())
1840
1851
goto err_occurred ;
1852
+ CHECK_RELEASED_INT_AGAIN (self );
1841
1853
PACK_SINGLE (ptr , llu , unsigned long long);
1842
1854
break ;
1843
1855
@@ -1846,12 +1858,14 @@ pack_single(char *ptr, PyObject *item, const char *fmt)
1846
1858
zd = pylong_as_zd (item );
1847
1859
if (zd == -1 && PyErr_Occurred ())
1848
1860
goto err_occurred ;
1861
+ CHECK_RELEASED_INT_AGAIN (self );
1849
1862
PACK_SINGLE (ptr , zd , Py_ssize_t );
1850
1863
break ;
1851
1864
case 'N' :
1852
1865
zu = pylong_as_zu (item );
1853
1866
if (zu == (size_t )-1 && PyErr_Occurred ())
1854
1867
goto err_occurred ;
1868
+ CHECK_RELEASED_INT_AGAIN (self );
1855
1869
PACK_SINGLE (ptr , zu , size_t );
1856
1870
break ;
1857
1871
@@ -1860,6 +1874,7 @@ pack_single(char *ptr, PyObject *item, const char *fmt)
1860
1874
d = PyFloat_AsDouble (item );
1861
1875
if (d == -1.0 && PyErr_Occurred ())
1862
1876
goto err_occurred ;
1877
+ CHECK_RELEASED_INT_AGAIN (self );
1863
1878
if (fmt [0 ] == 'f' ) {
1864
1879
PACK_SINGLE (ptr , d , float );
1865
1880
}
@@ -1873,6 +1888,7 @@ pack_single(char *ptr, PyObject *item, const char *fmt)
1873
1888
ld = PyObject_IsTrue (item );
1874
1889
if (ld < 0 )
1875
1890
return -1 ; /* preserve original error */
1891
+ CHECK_RELEASED_INT_AGAIN (self );
1876
1892
PACK_SINGLE (ptr , ld , _Bool );
1877
1893
break ;
1878
1894
@@ -1890,6 +1906,7 @@ pack_single(char *ptr, PyObject *item, const char *fmt)
1890
1906
p = PyLong_AsVoidPtr (item );
1891
1907
if (p == NULL && PyErr_Occurred ())
1892
1908
goto err_occurred ;
1909
+ CHECK_RELEASED_INT_AGAIN (self );
1893
1910
PACK_SINGLE (ptr , p , void * );
1894
1911
break ;
1895
1912
@@ -2056,7 +2073,7 @@ adjust_fmt(const Py_buffer *view)
2056
2073
2057
2074
/* Base case for multi-dimensional unpacking. Assumption: ndim == 1. */
2058
2075
static 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 ,
2060
2077
const Py_ssize_t * strides , const Py_ssize_t * suboffsets ,
2061
2078
const char * fmt )
2062
2079
{
@@ -2069,7 +2086,7 @@ tolist_base(const char *ptr, const Py_ssize_t *shape,
2069
2086
2070
2087
for (i = 0 ; i < shape [0 ]; ptr += strides [0 ], i ++ ) {
2071
2088
const char * xptr = ADJUST_PTR (ptr , suboffsets , 0 );
2072
- item = unpack_single (xptr , fmt );
2089
+ item = unpack_single (self , xptr , fmt );
2073
2090
if (item == NULL ) {
2074
2091
Py_DECREF (lst );
2075
2092
return NULL ;
@@ -2083,7 +2100,7 @@ tolist_base(const char *ptr, const Py_ssize_t *shape,
2083
2100
/* Unpack a multi-dimensional array into a nested list.
2084
2101
Assumption: ndim >= 1. */
2085
2102
static 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 ,
2087
2104
const Py_ssize_t * strides , const Py_ssize_t * suboffsets ,
2088
2105
const char * fmt )
2089
2106
{
@@ -2095,15 +2112,15 @@ tolist_rec(const char *ptr, Py_ssize_t ndim, const Py_ssize_t *shape,
2095
2112
assert (strides != NULL );
2096
2113
2097
2114
if (ndim == 1 )
2098
- return tolist_base (ptr , shape , strides , suboffsets , fmt );
2115
+ return tolist_base (self , ptr , shape , strides , suboffsets , fmt );
2099
2116
2100
2117
lst = PyList_New (shape [0 ]);
2101
2118
if (lst == NULL )
2102
2119
return NULL ;
2103
2120
2104
2121
for (i = 0 ; i < shape [0 ]; ptr += strides [0 ], i ++ ) {
2105
2122
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 ,
2107
2124
strides + 1 , suboffsets ? suboffsets + 1 : NULL ,
2108
2125
fmt );
2109
2126
if (item == NULL ) {
@@ -2137,15 +2154,15 @@ memoryview_tolist_impl(PyMemoryViewObject *self)
2137
2154
if (fmt == NULL )
2138
2155
return NULL ;
2139
2156
if (view -> ndim == 0 ) {
2140
- return unpack_single (view -> buf , fmt );
2157
+ return unpack_single (self , view -> buf , fmt );
2141
2158
}
2142
2159
else if (view -> ndim == 1 ) {
2143
- return tolist_base (view -> buf , view -> shape ,
2160
+ return tolist_base (self , view -> buf , view -> shape ,
2144
2161
view -> strides , view -> suboffsets ,
2145
2162
fmt );
2146
2163
}
2147
2164
else {
2148
- return tolist_rec (view -> buf , view -> ndim , view -> shape ,
2165
+ return tolist_rec (self , view -> buf , view -> ndim , view -> shape ,
2149
2166
view -> strides , view -> suboffsets ,
2150
2167
fmt );
2151
2168
}
@@ -2353,7 +2370,7 @@ memory_item(PyMemoryViewObject *self, Py_ssize_t index)
2353
2370
char * ptr = ptr_from_index (view , index );
2354
2371
if (ptr == NULL )
2355
2372
return NULL ;
2356
- return unpack_single (ptr , fmt );
2373
+ return unpack_single (self , ptr , fmt );
2357
2374
}
2358
2375
2359
2376
PyErr_SetString (PyExc_NotImplementedError ,
@@ -2384,7 +2401,7 @@ memory_item_multi(PyMemoryViewObject *self, PyObject *tup)
2384
2401
ptr = ptr_from_tuple (view , tup );
2385
2402
if (ptr == NULL )
2386
2403
return NULL ;
2387
- return unpack_single (ptr , fmt );
2404
+ return unpack_single (self , ptr , fmt );
2388
2405
}
2389
2406
2390
2407
static inline int
@@ -2471,7 +2488,7 @@ memory_subscript(PyMemoryViewObject *self, PyObject *key)
2471
2488
const char * fmt = adjust_fmt (view );
2472
2489
if (fmt == NULL )
2473
2490
return NULL ;
2474
- return unpack_single (view -> buf , fmt );
2491
+ return unpack_single (self , view -> buf , fmt );
2475
2492
}
2476
2493
else if (key == Py_Ellipsis ) {
2477
2494
Py_INCREF (self );
@@ -2546,7 +2563,7 @@ memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
2546
2563
if (key == Py_Ellipsis ||
2547
2564
(PyTuple_Check (key ) && PyTuple_GET_SIZE (key )== 0 )) {
2548
2565
ptr = (char * )view -> buf ;
2549
- return pack_single (ptr , value , fmt );
2566
+ return pack_single (self , ptr , value , fmt );
2550
2567
}
2551
2568
else {
2552
2569
PyErr_SetString (PyExc_TypeError ,
@@ -2568,7 +2585,7 @@ memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
2568
2585
ptr = ptr_from_index (view , index );
2569
2586
if (ptr == NULL )
2570
2587
return -1 ;
2571
- return pack_single (ptr , value , fmt );
2588
+ return pack_single (self , ptr , value , fmt );
2572
2589
}
2573
2590
/* one-dimensional: fast path */
2574
2591
if (PySlice_Check (key ) && view -> ndim == 1 ) {
@@ -2591,7 +2608,7 @@ memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
2591
2608
goto end_block ;
2592
2609
dest .len = dest .shape [0 ] * dest .itemsize ;
2593
2610
2594
- ret = copy_single (& dest , & src );
2611
+ ret = copy_single (self , & dest , & src );
2595
2612
2596
2613
end_block :
2597
2614
PyBuffer_Release (& src );
@@ -2607,7 +2624,7 @@ memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
2607
2624
ptr = ptr_from_tuple (view , key );
2608
2625
if (ptr == NULL )
2609
2626
return -1 ;
2610
- return pack_single (ptr , value , fmt );
2627
+ return pack_single (self , ptr , value , fmt );
2611
2628
}
2612
2629
if (PySlice_Check (key ) || is_multislice (key )) {
2613
2630
/* Call memory_subscript() to produce a sliced lvalue, then copy
@@ -3208,7 +3225,7 @@ memoryiter_next(memoryiterobject *it)
3208
3225
if (ptr == NULL ) {
3209
3226
return NULL ;
3210
3227
}
3211
- return unpack_single (ptr , it -> it_fmt );
3228
+ return unpack_single (seq , ptr , it -> it_fmt );
3212
3229
}
3213
3230
3214
3231
it -> it_seq = NULL ;
0 commit comments