summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorJelle Zijlstra <jelle.zijlstra@gmail.com>2023-05-12 05:22:40 (GMT)
committerGitHub <noreply@github.com>2023-05-12 05:22:40 (GMT)
commita0a98ddb31591357bead4694b21717cb4034924f (patch)
tree05269c152cc5a41d126dba845faaa2f08d726657 /Objects
parentac66cc17f21653b66321b50d0a1f792982fca21f (diff)
downloadcpython-a0a98ddb31591357bead4694b21717cb4034924f.zip
cpython-a0a98ddb31591357bead4694b21717cb4034924f.tar.gz
cpython-a0a98ddb31591357bead4694b21717cb4034924f.tar.bz2
gh-104371: Fix calls to `__release_buffer__` while an exception is active (#104378)
Co-authored-by: Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com>
Diffstat (limited to 'Objects')
-rw-r--r--Objects/typeobject.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index f1745c9..f40e197 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -9117,6 +9117,12 @@ releasebuffer_maybe_call_super(PyObject *self, Py_buffer *buffer)
static void
releasebuffer_call_python(PyObject *self, Py_buffer *buffer)
{
+ // bf_releasebuffer may be called while an exception is already active.
+ // We have no way to report additional errors up the stack, because
+ // this slot returns void, so we simply stash away the active exception
+ // and restore it after the call to Python returns.
+ PyObject *exc = PyErr_GetRaisedException();
+
PyObject *mv;
bool is_buffer_wrapper = Py_TYPE(buffer->obj) == &_PyBufferWrapper_Type;
if (is_buffer_wrapper) {
@@ -9124,7 +9130,7 @@ releasebuffer_call_python(PyObject *self, Py_buffer *buffer)
// __release_buffer__() that __buffer__() returned.
PyBufferWrapper *bw = (PyBufferWrapper *)buffer->obj;
if (bw->mv == NULL) {
- return;
+ goto end;
}
mv = Py_NewRef(bw->mv);
}
@@ -9134,7 +9140,7 @@ releasebuffer_call_python(PyObject *self, Py_buffer *buffer)
mv = PyMemoryView_FromBuffer(buffer);
if (mv == NULL) {
PyErr_WriteUnraisable(self);
- return;
+ goto end;
}
// Set the memoryview to restricted mode, which forbids
// users from saving any reference to the underlying buffer
@@ -9155,6 +9161,10 @@ releasebuffer_call_python(PyObject *self, Py_buffer *buffer)
PyObject_CallMethodNoArgs(mv, &_Py_ID(release));
}
Py_DECREF(mv);
+end:
+ assert(!PyErr_Occurred());
+
+ PyErr_SetRaisedException(exc);
}
/*