Skip to content

Commit

Permalink
pythongh-114685: PyBuffer_FillInfo now raises on PyBUF_{READ,WRITE}
Browse files Browse the repository at this point in the history
  • Loading branch information
sobolevn committed Jan 31, 2024
1 parent 1c2ea8b commit 350a6e7
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 5 deletions.
13 changes: 13 additions & 0 deletions Lib/test/test_buffer.py
Expand Up @@ -4591,6 +4591,19 @@ def test_c_buffer_invalid_flags(self):
self.assertRaises(SystemError, buf.__buffer__, PyBUF_READ)
self.assertRaises(SystemError, buf.__buffer__, PyBUF_WRITE)

@unittest.skipIf(_testcapi is None, "requires _testcapi")
def test_c_fill_buffer_invalid_flags(self):
# PyBuffer_FillInfo
self.assertRaises(SystemError, _testcapi.buffer_fill_info,
"abc", 0, PyBUF_READ)
self.assertRaises(SystemError, _testcapi.buffer_fill_info,
"abc", 0, PyBUF_WRITE)

@unittest.skipIf(_testcapi is None, "requires _testcapi")
def test_c_fill_buffer_readonly_and_writable(self):
self.assertRaises(BufferError, _testcapi.buffer_fill_info,
"abc", 1, PyBUF_WRITABLE)

def test_inheritance(self):
class A(bytearray):
def __buffer__(self, flags):
Expand Down
@@ -0,0 +1,3 @@
:c:func:`PyBuffer_FillInfo` now raises a :exc:`SystemError` if called with
:c:macro:`PyBUF_READ` or :c:macro:`PyBUF_WRITE` as flags. These flags should
only be used with the ``PyMemoryView_*`` C API.
20 changes: 20 additions & 0 deletions Modules/_testcapimodule.c
Expand Up @@ -1261,6 +1261,25 @@ make_memoryview_from_NULL_pointer(PyObject *self, PyObject *Py_UNUSED(ignored))
return PyMemoryView_FromBuffer(&info);
}

static PyObject *
buffer_fill_info(PyObject *self, PyObject *args)
{
Py_buffer info;
const char *data;
Py_ssize_t size;
int readonly;
int flags;

if (!PyArg_ParseTuple(args, "s#ii:buffer_fill_info",
&data, &size, &readonly, &flags)) {
return NULL;
}

if (PyBuffer_FillInfo(&info, NULL, (void *)data, size, readonly, flags) < 0)
return NULL;
return PyMemoryView_FromBuffer(&info);
}

static PyObject *
test_from_contiguous(PyObject* self, PyObject *Py_UNUSED(ignored))
{
Expand Down Expand Up @@ -3314,6 +3333,7 @@ static PyMethodDef TestMethods[] = {
{"eval_code_ex", eval_eval_code_ex, METH_VARARGS},
{"make_memoryview_from_NULL_pointer", make_memoryview_from_NULL_pointer,
METH_NOARGS},
{"buffer_fill_info", buffer_fill_info, METH_VARARGS},
{"crash_no_current_thread", crash_no_current_thread, METH_NOARGS},
{"test_current_tstate_matches", test_current_tstate_matches, METH_NOARGS},
{"run_in_subinterp", run_in_subinterp, METH_VARARGS},
Expand Down
16 changes: 11 additions & 5 deletions Objects/abstract.c
Expand Up @@ -767,11 +767,17 @@ PyBuffer_FillInfo(Py_buffer *view, PyObject *obj, void *buf, Py_ssize_t len,
return -1;
}

if (((flags & PyBUF_WRITABLE) == PyBUF_WRITABLE) &&
(readonly == 1)) {
PyErr_SetString(PyExc_BufferError,
"Object is not writable.");
return -1;
if (flags != PyBUF_SIMPLE) { /* fast path */
if (flags == PyBUF_READ || flags == PyBUF_WRITE) {
PyErr_BadInternalCall();
return -1;
}
if (((flags & PyBUF_WRITABLE) == PyBUF_WRITABLE) &&
(readonly == 1)) {
PyErr_SetString(PyExc_BufferError,
"Object is not writable.");
return -1;
}
}

view->obj = Py_XNewRef(obj);
Expand Down

0 comments on commit 350a6e7

Please sign in to comment.