@@ -193,6 +193,11 @@ PyTypeObject _PyManagedBuffer_Type = {
193
193
return -1; \
194
194
}
195
195
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
+
196
201
#define CHECK_LIST_OR_TUPLE (v ) \
197
202
if (!PyList_Check(v) && !PyTuple_Check(v)) { \
198
203
PyErr_SetString(PyExc_TypeError, \
@@ -381,8 +386,9 @@ copy_rec(const Py_ssize_t *shape, Py_ssize_t ndim, Py_ssize_t itemsize,
381
386
382
387
/* Faster copying of one-dimensional arrays. */
383
388
static 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 )
385
390
{
391
+ CHECK_RELEASED_INT_AGAIN (self );
386
392
char * mem = NULL ;
387
393
388
394
assert (dest -> ndim == 1 );
@@ -1677,7 +1683,7 @@ pylong_as_zu(PyObject *item)
1677
1683
module syntax. This function is very sensitive to small changes. With this
1678
1684
layout gcc automatically generates a fast jump table. */
1679
1685
static inline PyObject *
1680
- unpack_single (const char * ptr , const char * fmt )
1686
+ unpack_single (PyMemoryViewObject * self , const char * ptr , const char * fmt )
1681
1687
{
1682
1688
unsigned long long llu ;
1683
1689
unsigned long lu ;
@@ -1689,6 +1695,8 @@ unpack_single(const char *ptr, const char *fmt)
1689
1695
unsigned char uc ;
1690
1696
void * p ;
1691
1697
1698
+ CHECK_RELEASED_AGAIN (self );
1699
+
1692
1700
switch (fmt [0 ]) {
1693
1701
1694
1702
/* signed integers and fast path for 'B' */
@@ -1767,7 +1775,7 @@ unpack_single(const char *ptr, const char *fmt)
1767
1775
/* Pack a single item. 'fmt' can be any native format character in
1768
1776
struct module syntax. */
1769
1777
static int
1770
- pack_single (char * ptr , PyObject * item , const char * fmt )
1778
+ pack_single (PyMemoryViewObject * self , char * ptr , PyObject * item , const char * fmt )
1771
1779
{
1772
1780
unsigned long long llu ;
1773
1781
unsigned long lu ;
@@ -1784,6 +1792,7 @@ pack_single(char *ptr, PyObject *item, const char *fmt)
1784
1792
ld = pylong_as_ld (item );
1785
1793
if (ld == -1 && PyErr_Occurred ())
1786
1794
goto err_occurred ;
1795
+ CHECK_RELEASED_INT_AGAIN (self );
1787
1796
switch (fmt [0 ]) {
1788
1797
case 'b' :
1789
1798
if (ld < SCHAR_MIN || ld > SCHAR_MAX ) goto err_range ;
@@ -1804,6 +1813,7 @@ pack_single(char *ptr, PyObject *item, const char *fmt)
1804
1813
lu = pylong_as_lu (item );
1805
1814
if (lu == (unsigned long )-1 && PyErr_Occurred ())
1806
1815
goto err_occurred ;
1816
+ CHECK_RELEASED_INT_AGAIN (self );
1807
1817
switch (fmt [0 ]) {
1808
1818
case 'B' :
1809
1819
if (lu > UCHAR_MAX ) goto err_range ;
@@ -1824,12 +1834,14 @@ pack_single(char *ptr, PyObject *item, const char *fmt)
1824
1834
lld = pylong_as_lld (item );
1825
1835
if (lld == -1 && PyErr_Occurred ())
1826
1836
goto err_occurred ;
1837
+ CHECK_RELEASED_INT_AGAIN (self );
1827
1838
PACK_SINGLE (ptr , lld , long long );
1828
1839
break ;
1829
1840
case 'Q' :
1830
1841
llu = pylong_as_llu (item );
1831
1842
if (llu == (unsigned long long )-1 && PyErr_Occurred ())
1832
1843
goto err_occurred ;
1844
+ CHECK_RELEASED_INT_AGAIN (self );
1833
1845
PACK_SINGLE (ptr , llu , unsigned long long);
1834
1846
break ;
1835
1847
@@ -1838,12 +1850,14 @@ pack_single(char *ptr, PyObject *item, const char *fmt)
1838
1850
zd = pylong_as_zd (item );
1839
1851
if (zd == -1 && PyErr_Occurred ())
1840
1852
goto err_occurred ;
1853
+ CHECK_RELEASED_INT_AGAIN (self );
1841
1854
PACK_SINGLE (ptr , zd , Py_ssize_t );
1842
1855
break ;
1843
1856
case 'N' :
1844
1857
zu = pylong_as_zu (item );
1845
1858
if (zu == (size_t )-1 && PyErr_Occurred ())
1846
1859
goto err_occurred ;
1860
+ CHECK_RELEASED_INT_AGAIN (self );
1847
1861
PACK_SINGLE (ptr , zu , size_t );
1848
1862
break ;
1849
1863
@@ -1852,6 +1866,7 @@ pack_single(char *ptr, PyObject *item, const char *fmt)
1852
1866
d = PyFloat_AsDouble (item );
1853
1867
if (d == -1.0 && PyErr_Occurred ())
1854
1868
goto err_occurred ;
1869
+ CHECK_RELEASED_INT_AGAIN (self );
1855
1870
if (fmt [0 ] == 'f' ) {
1856
1871
PACK_SINGLE (ptr , d , float );
1857
1872
}
@@ -1865,6 +1880,7 @@ pack_single(char *ptr, PyObject *item, const char *fmt)
1865
1880
ld = PyObject_IsTrue (item );
1866
1881
if (ld < 0 )
1867
1882
return -1 ; /* preserve original error */
1883
+ CHECK_RELEASED_INT_AGAIN (self );
1868
1884
PACK_SINGLE (ptr , ld , _Bool );
1869
1885
break ;
1870
1886
@@ -1882,6 +1898,7 @@ pack_single(char *ptr, PyObject *item, const char *fmt)
1882
1898
p = PyLong_AsVoidPtr (item );
1883
1899
if (p == NULL && PyErr_Occurred ())
1884
1900
goto err_occurred ;
1901
+ CHECK_RELEASED_INT_AGAIN (self );
1885
1902
PACK_SINGLE (ptr , p , void * );
1886
1903
break ;
1887
1904
@@ -2042,7 +2059,7 @@ adjust_fmt(const Py_buffer *view)
2042
2059
2043
2060
/* Base case for multi-dimensional unpacking. Assumption: ndim == 1. */
2044
2061
static PyObject *
2045
- tolist_base (const char * ptr , const Py_ssize_t * shape ,
2062
+ tolist_base (PyMemoryViewObject * self , const char * ptr , const Py_ssize_t * shape ,
2046
2063
const Py_ssize_t * strides , const Py_ssize_t * suboffsets ,
2047
2064
const char * fmt )
2048
2065
{
@@ -2055,7 +2072,7 @@ tolist_base(const char *ptr, const Py_ssize_t *shape,
2055
2072
2056
2073
for (i = 0 ; i < shape [0 ]; ptr += strides [0 ], i ++ ) {
2057
2074
const char * xptr = ADJUST_PTR (ptr , suboffsets , 0 );
2058
- item = unpack_single (xptr , fmt );
2075
+ item = unpack_single (self , xptr , fmt );
2059
2076
if (item == NULL ) {
2060
2077
Py_DECREF (lst );
2061
2078
return NULL ;
@@ -2069,7 +2086,7 @@ tolist_base(const char *ptr, const Py_ssize_t *shape,
2069
2086
/* Unpack a multi-dimensional array into a nested list.
2070
2087
Assumption: ndim >= 1. */
2071
2088
static PyObject *
2072
- tolist_rec (const char * ptr , Py_ssize_t ndim , const Py_ssize_t * shape ,
2089
+ tolist_rec (PyMemoryViewObject * self , const char * ptr , Py_ssize_t ndim , const Py_ssize_t * shape ,
2073
2090
const Py_ssize_t * strides , const Py_ssize_t * suboffsets ,
2074
2091
const char * fmt )
2075
2092
{
@@ -2081,15 +2098,15 @@ tolist_rec(const char *ptr, Py_ssize_t ndim, const Py_ssize_t *shape,
2081
2098
assert (strides != NULL );
2082
2099
2083
2100
if (ndim == 1 )
2084
- return tolist_base (ptr , shape , strides , suboffsets , fmt );
2101
+ return tolist_base (self , ptr , shape , strides , suboffsets , fmt );
2085
2102
2086
2103
lst = PyList_New (shape [0 ]);
2087
2104
if (lst == NULL )
2088
2105
return NULL ;
2089
2106
2090
2107
for (i = 0 ; i < shape [0 ]; ptr += strides [0 ], i ++ ) {
2091
2108
const char * xptr = ADJUST_PTR (ptr , suboffsets , 0 );
2092
- item = tolist_rec (xptr , ndim - 1 , shape + 1 ,
2109
+ item = tolist_rec (self , xptr , ndim - 1 , shape + 1 ,
2093
2110
strides + 1 , suboffsets ? suboffsets + 1 : NULL ,
2094
2111
fmt );
2095
2112
if (item == NULL ) {
@@ -2123,15 +2140,15 @@ memoryview_tolist_impl(PyMemoryViewObject *self)
2123
2140
if (fmt == NULL )
2124
2141
return NULL ;
2125
2142
if (view -> ndim == 0 ) {
2126
- return unpack_single (view -> buf , fmt );
2143
+ return unpack_single (self , view -> buf , fmt );
2127
2144
}
2128
2145
else if (view -> ndim == 1 ) {
2129
- return tolist_base (view -> buf , view -> shape ,
2146
+ return tolist_base (self , view -> buf , view -> shape ,
2130
2147
view -> strides , view -> suboffsets ,
2131
2148
fmt );
2132
2149
}
2133
2150
else {
2134
- return tolist_rec (view -> buf , view -> ndim , view -> shape ,
2151
+ return tolist_rec (self , view -> buf , view -> ndim , view -> shape ,
2135
2152
view -> strides , view -> suboffsets ,
2136
2153
fmt );
2137
2154
}
@@ -2339,7 +2356,7 @@ memory_item(PyMemoryViewObject *self, Py_ssize_t index)
2339
2356
char * ptr = ptr_from_index (view , index );
2340
2357
if (ptr == NULL )
2341
2358
return NULL ;
2342
- return unpack_single (ptr , fmt );
2359
+ return unpack_single (self , ptr , fmt );
2343
2360
}
2344
2361
2345
2362
PyErr_SetString (PyExc_NotImplementedError ,
@@ -2370,7 +2387,7 @@ memory_item_multi(PyMemoryViewObject *self, PyObject *tup)
2370
2387
ptr = ptr_from_tuple (view , tup );
2371
2388
if (ptr == NULL )
2372
2389
return NULL ;
2373
- return unpack_single (ptr , fmt );
2390
+ return unpack_single (self , ptr , fmt );
2374
2391
}
2375
2392
2376
2393
static inline int
@@ -2457,7 +2474,7 @@ memory_subscript(PyMemoryViewObject *self, PyObject *key)
2457
2474
const char * fmt = adjust_fmt (view );
2458
2475
if (fmt == NULL )
2459
2476
return NULL ;
2460
- return unpack_single (view -> buf , fmt );
2477
+ return unpack_single (self , view -> buf , fmt );
2461
2478
}
2462
2479
else if (key == Py_Ellipsis ) {
2463
2480
Py_INCREF (self );
@@ -2532,7 +2549,7 @@ memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
2532
2549
if (key == Py_Ellipsis ||
2533
2550
(PyTuple_Check (key ) && PyTuple_GET_SIZE (key )== 0 )) {
2534
2551
ptr = (char * )view -> buf ;
2535
- return pack_single (ptr , value , fmt );
2552
+ return pack_single (self , ptr , value , fmt );
2536
2553
}
2537
2554
else {
2538
2555
PyErr_SetString (PyExc_TypeError ,
@@ -2554,7 +2571,7 @@ memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
2554
2571
ptr = ptr_from_index (view , index );
2555
2572
if (ptr == NULL )
2556
2573
return -1 ;
2557
- return pack_single (ptr , value , fmt );
2574
+ return pack_single (self , ptr , value , fmt );
2558
2575
}
2559
2576
/* one-dimensional: fast path */
2560
2577
if (PySlice_Check (key ) && view -> ndim == 1 ) {
@@ -2577,7 +2594,7 @@ memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
2577
2594
goto end_block ;
2578
2595
dest .len = dest .shape [0 ] * dest .itemsize ;
2579
2596
2580
- ret = copy_single (& dest , & src );
2597
+ ret = copy_single (self , & dest , & src );
2581
2598
2582
2599
end_block :
2583
2600
PyBuffer_Release (& src );
@@ -2593,7 +2610,7 @@ memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
2593
2610
ptr = ptr_from_tuple (view , key );
2594
2611
if (ptr == NULL )
2595
2612
return -1 ;
2596
- return pack_single (ptr , value , fmt );
2613
+ return pack_single (self , ptr , value , fmt );
2597
2614
}
2598
2615
if (PySlice_Check (key ) || is_multislice (key )) {
2599
2616
/* Call memory_subscript() to produce a sliced lvalue, then copy
@@ -3194,7 +3211,7 @@ memoryiter_next(memoryiterobject *it)
3194
3211
if (ptr == NULL ) {
3195
3212
return NULL ;
3196
3213
}
3197
- return unpack_single (ptr , it -> it_fmt );
3214
+ return unpack_single (seq , ptr , it -> it_fmt );
3198
3215
}
3199
3216
3200
3217
it -> it_seq = NULL ;
0 commit comments