@@ -3683,28 +3683,44 @@ PyArray_FromBuffer(PyObject *buf, PyArray_Descr *type,
3683
3683
return NULL ;
3684
3684
}
3685
3685
3686
+ /*
3687
+ * The array check is probably unnecessary. It preserves the base for
3688
+ * arrays. This is the "old" buffer protocol, which had no release logic.
3689
+ * (It was assumed that the result is always a view.)
3690
+ *
3691
+ * NOTE: We could also check if `bf_releasebuffer` is defined which should
3692
+ * be the most precise and safe thing to do. But that should only be
3693
+ * necessary if unexpected backcompat issues are found downstream.
3694
+ */
3695
+ if (!PyArray_Check (buf )) {
3696
+ buf = PyMemoryView_FromObject (buf );
3697
+ if (buf == NULL ) {
3698
+ return NULL ;
3699
+ }
3700
+ }
3701
+ else {
3702
+ Py_INCREF (buf );
3703
+ }
3704
+
3686
3705
if (PyObject_GetBuffer (buf , & view , PyBUF_WRITABLE |PyBUF_SIMPLE ) < 0 ) {
3687
3706
writeable = 0 ;
3688
3707
PyErr_Clear ();
3689
3708
if (PyObject_GetBuffer (buf , & view , PyBUF_SIMPLE ) < 0 ) {
3709
+ Py_DECREF (buf );
3690
3710
Py_DECREF (type );
3691
3711
return NULL ;
3692
3712
}
3693
3713
}
3694
3714
data = (char * )view .buf ;
3695
3715
ts = view .len ;
3696
- /*
3697
- * In Python 3 both of the deprecated functions PyObject_AsWriteBuffer and
3698
- * PyObject_AsReadBuffer that this code replaces release the buffer. It is
3699
- * up to the object that supplies the buffer to guarantee that the buffer
3700
- * sticks around after the release.
3701
- */
3716
+ /* `buf` is an array or a memoryview; so we know `view` does not own data */
3702
3717
PyBuffer_Release (& view );
3703
3718
3704
3719
if ((offset < 0 ) || (offset > ts )) {
3705
3720
PyErr_Format (PyExc_ValueError ,
3706
3721
"offset must be non-negative and no greater than buffer " \
3707
3722
"length (%" NPY_INTP_FMT ")" , (npy_intp )ts );
3723
+ Py_DECREF (buf );
3708
3724
Py_DECREF (type );
3709
3725
return NULL ;
3710
3726
}
@@ -3717,13 +3733,15 @@ PyArray_FromBuffer(PyObject *buf, PyArray_Descr *type,
3717
3733
if (itemsize == 0 ) {
3718
3734
PyErr_SetString (PyExc_ValueError ,
3719
3735
"cannot determine count if itemsize is 0" );
3736
+ Py_DECREF (buf );
3720
3737
Py_DECREF (type );
3721
3738
return NULL ;
3722
3739
}
3723
3740
if (s % itemsize != 0 ) {
3724
3741
PyErr_SetString (PyExc_ValueError ,
3725
3742
"buffer size must be a multiple" \
3726
3743
" of element size" );
3744
+ Py_DECREF (buf );
3727
3745
Py_DECREF (type );
3728
3746
return NULL ;
3729
3747
}
@@ -3734,6 +3752,7 @@ PyArray_FromBuffer(PyObject *buf, PyArray_Descr *type,
3734
3752
PyErr_SetString (PyExc_ValueError ,
3735
3753
"buffer is smaller than requested" \
3736
3754
" size" );
3755
+ Py_DECREF (buf );
3737
3756
Py_DECREF (type );
3738
3757
return NULL ;
3739
3758
}
@@ -3743,6 +3762,7 @@ PyArray_FromBuffer(PyObject *buf, PyArray_Descr *type,
3743
3762
& PyArray_Type , type ,
3744
3763
1 , & n , NULL , data ,
3745
3764
NPY_ARRAY_DEFAULT , NULL , buf );
3765
+ Py_DECREF (buf );
3746
3766
if (ret == NULL ) {
3747
3767
return NULL ;
3748
3768
}
0 commit comments