@@ -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
@@ -2048,7 +2065,7 @@ adjust_fmt(const Py_buffer *view)
2048
2065
2049
2066
/* Base case for multi-dimensional unpacking. Assumption: ndim == 1. */
2050
2067
static 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 ,
2052
2069
const Py_ssize_t * strides , const Py_ssize_t * suboffsets ,
2053
2070
const char * fmt )
2054
2071
{
@@ -2061,7 +2078,7 @@ tolist_base(const char *ptr, const Py_ssize_t *shape,
2061
2078
2062
2079
for (i = 0 ; i < shape [0 ]; ptr += strides [0 ], i ++ ) {
2063
2080
const char * xptr = ADJUST_PTR (ptr , suboffsets , 0 );
2064
- item = unpack_single (xptr , fmt );
2081
+ item = unpack_single (self , xptr , fmt );
2065
2082
if (item == NULL ) {
2066
2083
Py_DECREF (lst );
2067
2084
return NULL ;
@@ -2075,7 +2092,7 @@ tolist_base(const char *ptr, const Py_ssize_t *shape,
2075
2092
/* Unpack a multi-dimensional array into a nested list.
2076
2093
Assumption: ndim >= 1. */
2077
2094
static 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 ,
2079
2096
const Py_ssize_t * strides , const Py_ssize_t * suboffsets ,
2080
2097
const char * fmt )
2081
2098
{
@@ -2087,15 +2104,15 @@ tolist_rec(const char *ptr, Py_ssize_t ndim, const Py_ssize_t *shape,
2087
2104
assert (strides != NULL );
2088
2105
2089
2106
if (ndim == 1 )
2090
- return tolist_base (ptr , shape , strides , suboffsets , fmt );
2107
+ return tolist_base (self , ptr , shape , strides , suboffsets , fmt );
2091
2108
2092
2109
lst = PyList_New (shape [0 ]);
2093
2110
if (lst == NULL )
2094
2111
return NULL ;
2095
2112
2096
2113
for (i = 0 ; i < shape [0 ]; ptr += strides [0 ], i ++ ) {
2097
2114
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 ,
2099
2116
strides + 1 , suboffsets ? suboffsets + 1 : NULL ,
2100
2117
fmt );
2101
2118
if (item == NULL ) {
@@ -2129,15 +2146,15 @@ memoryview_tolist_impl(PyMemoryViewObject *self)
2129
2146
if (fmt == NULL )
2130
2147
return NULL ;
2131
2148
if (view -> ndim == 0 ) {
2132
- return unpack_single (view -> buf , fmt );
2149
+ return unpack_single (self , view -> buf , fmt );
2133
2150
}
2134
2151
else if (view -> ndim == 1 ) {
2135
- return tolist_base (view -> buf , view -> shape ,
2152
+ return tolist_base (self , view -> buf , view -> shape ,
2136
2153
view -> strides , view -> suboffsets ,
2137
2154
fmt );
2138
2155
}
2139
2156
else {
2140
- return tolist_rec (view -> buf , view -> ndim , view -> shape ,
2157
+ return tolist_rec (self , view -> buf , view -> ndim , view -> shape ,
2141
2158
view -> strides , view -> suboffsets ,
2142
2159
fmt );
2143
2160
}
@@ -2345,7 +2362,7 @@ memory_item(PyMemoryViewObject *self, Py_ssize_t index)
2345
2362
char * ptr = ptr_from_index (view , index );
2346
2363
if (ptr == NULL )
2347
2364
return NULL ;
2348
- return unpack_single (ptr , fmt );
2365
+ return unpack_single (self , ptr , fmt );
2349
2366
}
2350
2367
2351
2368
PyErr_SetString (PyExc_NotImplementedError ,
@@ -2376,7 +2393,7 @@ memory_item_multi(PyMemoryViewObject *self, PyObject *tup)
2376
2393
ptr = ptr_from_tuple (view , tup );
2377
2394
if (ptr == NULL )
2378
2395
return NULL ;
2379
- return unpack_single (ptr , fmt );
2396
+ return unpack_single (self , ptr , fmt );
2380
2397
}
2381
2398
2382
2399
static inline int
@@ -2463,7 +2480,7 @@ memory_subscript(PyMemoryViewObject *self, PyObject *key)
2463
2480
const char * fmt = adjust_fmt (view );
2464
2481
if (fmt == NULL )
2465
2482
return NULL ;
2466
- return unpack_single (view -> buf , fmt );
2483
+ return unpack_single (self , view -> buf , fmt );
2467
2484
}
2468
2485
else if (key == Py_Ellipsis ) {
2469
2486
Py_INCREF (self );
@@ -2538,7 +2555,7 @@ memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
2538
2555
if (key == Py_Ellipsis ||
2539
2556
(PyTuple_Check (key ) && PyTuple_GET_SIZE (key )== 0 )) {
2540
2557
ptr = (char * )view -> buf ;
2541
- return pack_single (ptr , value , fmt );
2558
+ return pack_single (self , ptr , value , fmt );
2542
2559
}
2543
2560
else {
2544
2561
PyErr_SetString (PyExc_TypeError ,
@@ -2560,7 +2577,7 @@ memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
2560
2577
ptr = ptr_from_index (view , index );
2561
2578
if (ptr == NULL )
2562
2579
return -1 ;
2563
- return pack_single (ptr , value , fmt );
2580
+ return pack_single (self , ptr , value , fmt );
2564
2581
}
2565
2582
/* one-dimensional: fast path */
2566
2583
if (PySlice_Check (key ) && view -> ndim == 1 ) {
@@ -2583,7 +2600,7 @@ memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
2583
2600
goto end_block ;
2584
2601
dest .len = dest .shape [0 ] * dest .itemsize ;
2585
2602
2586
- ret = copy_single (& dest , & src );
2603
+ ret = copy_single (self , & dest , & src );
2587
2604
2588
2605
end_block :
2589
2606
PyBuffer_Release (& src );
@@ -2599,7 +2616,7 @@ memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
2599
2616
ptr = ptr_from_tuple (view , key );
2600
2617
if (ptr == NULL )
2601
2618
return -1 ;
2602
- return pack_single (ptr , value , fmt );
2619
+ return pack_single (self , ptr , value , fmt );
2603
2620
}
2604
2621
if (PySlice_Check (key ) || is_multislice (key )) {
2605
2622
/* Call memory_subscript() to produce a sliced lvalue, then copy
@@ -3200,7 +3217,7 @@ memoryiter_next(memoryiterobject *it)
3200
3217
if (ptr == NULL ) {
3201
3218
return NULL ;
3202
3219
}
3203
- return unpack_single (ptr , it -> it_fmt );
3220
+ return unpack_single (seq , ptr , it -> it_fmt );
3204
3221
}
3205
3222
3206
3223
it -> it_seq = NULL ;
0 commit comments