Skip to content

Commit b7688ef

Browse files
gh-114685: Check flags in PyObject_GetBuffer() (GH-114707)
PyObject_GetBuffer() now raises a SystemError if called with PyBUF_READ or PyBUF_WRITE as flags. These flags should only be used with the PyMemoryView_* C API.
1 parent 7a93db4 commit b7688ef

File tree

4 files changed

+19
-2
lines changed

4 files changed

+19
-2
lines changed

Lib/test/test_buffer.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4585,6 +4585,12 @@ def test_c_buffer(self):
45854585
buf.__release_buffer__(mv)
45864586
self.assertEqual(buf.references, 0)
45874587

4588+
@unittest.skipIf(_testcapi is None, "requires _testcapi")
4589+
def test_c_buffer_invalid_flags(self):
4590+
buf = _testcapi.testBuf()
4591+
self.assertRaises(SystemError, buf.__buffer__, PyBUF_READ)
4592+
self.assertRaises(SystemError, buf.__buffer__, PyBUF_WRITE)
4593+
45884594
def test_inheritance(self):
45894595
class A(bytearray):
45904596
def __buffer__(self, flags):
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
:c:func:`PyObject_GetBuffer` now raises a :exc:`SystemError` if called with
2+
:c:macro:`PyBUF_READ` or :c:macro:`PyBUF_WRITE` as flags. These flags should
3+
only be used with the ``PyMemoryView_*`` C API.

Modules/_testcapi/buffer.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,10 @@ static int
5454
testbuf_getbuf(testBufObject *self, Py_buffer *view, int flags)
5555
{
5656
int buf = PyObject_GetBuffer(self->obj, view, flags);
57-
Py_SETREF(view->obj, Py_NewRef(self));
58-
self->references++;
57+
if (buf == 0) {
58+
Py_SETREF(view->obj, Py_NewRef(self));
59+
self->references++;
60+
}
5961
return buf;
6062
}
6163

Objects/abstract.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,12 @@ PyObject_AsWriteBuffer(PyObject *obj,
425425
int
426426
PyObject_GetBuffer(PyObject *obj, Py_buffer *view, int flags)
427427
{
428+
if (flags != PyBUF_SIMPLE) { /* fast path */
429+
if (flags == PyBUF_READ || flags == PyBUF_WRITE) {
430+
PyErr_BadInternalCall();
431+
return -1;
432+
}
433+
}
428434
PyBufferProcs *pb = Py_TYPE(obj)->tp_as_buffer;
429435

430436
if (pb == NULL || pb->bf_getbuffer == NULL) {

0 commit comments

Comments
 (0)