mirror of https://github.com/python/cpython
gh-114685: PyBuffer_FillInfo() now raises on PyBUF_{READ,WRITE} (GH-114802)
This commit is contained in:
parent
da8f9fb2ea
commit
929d44e15a
|
@ -4591,6 +4591,27 @@ class TestPythonBufferProtocol(unittest.TestCase):
|
||||||
self.assertRaises(SystemError, buf.__buffer__, PyBUF_READ)
|
self.assertRaises(SystemError, buf.__buffer__, PyBUF_READ)
|
||||||
self.assertRaises(SystemError, buf.__buffer__, PyBUF_WRITE)
|
self.assertRaises(SystemError, buf.__buffer__, PyBUF_WRITE)
|
||||||
|
|
||||||
|
@unittest.skipIf(_testcapi is None, "requires _testcapi")
|
||||||
|
def test_c_fill_buffer_invalid_flags(self):
|
||||||
|
# PyBuffer_FillInfo
|
||||||
|
source = b"abc"
|
||||||
|
self.assertRaises(SystemError, _testcapi.buffer_fill_info,
|
||||||
|
source, 0, PyBUF_READ)
|
||||||
|
self.assertRaises(SystemError, _testcapi.buffer_fill_info,
|
||||||
|
source, 0, PyBUF_WRITE)
|
||||||
|
|
||||||
|
@unittest.skipIf(_testcapi is None, "requires _testcapi")
|
||||||
|
def test_c_fill_buffer_readonly_and_writable(self):
|
||||||
|
source = b"abc"
|
||||||
|
with _testcapi.buffer_fill_info(source, 1, PyBUF_SIMPLE) as m:
|
||||||
|
self.assertEqual(bytes(m), b"abc")
|
||||||
|
self.assertTrue(m.readonly)
|
||||||
|
with _testcapi.buffer_fill_info(source, 0, PyBUF_WRITABLE) as m:
|
||||||
|
self.assertEqual(bytes(m), b"abc")
|
||||||
|
self.assertFalse(m.readonly)
|
||||||
|
self.assertRaises(BufferError, _testcapi.buffer_fill_info,
|
||||||
|
source, 1, PyBUF_WRITABLE)
|
||||||
|
|
||||||
def test_inheritance(self):
|
def test_inheritance(self):
|
||||||
class A(bytearray):
|
class A(bytearray):
|
||||||
def __buffer__(self, flags):
|
def __buffer__(self, flags):
|
||||||
|
|
|
@ -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.
|
|
@ -1261,6 +1261,26 @@ make_memoryview_from_NULL_pointer(PyObject *self, PyObject *Py_UNUSED(ignored))
|
||||||
return PyMemoryView_FromBuffer(&info);
|
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 *
|
static PyObject *
|
||||||
test_from_contiguous(PyObject* self, PyObject *Py_UNUSED(ignored))
|
test_from_contiguous(PyObject* self, PyObject *Py_UNUSED(ignored))
|
||||||
{
|
{
|
||||||
|
@ -3314,6 +3334,7 @@ static PyMethodDef TestMethods[] = {
|
||||||
{"eval_code_ex", eval_eval_code_ex, METH_VARARGS},
|
{"eval_code_ex", eval_eval_code_ex, METH_VARARGS},
|
||||||
{"make_memoryview_from_NULL_pointer", make_memoryview_from_NULL_pointer,
|
{"make_memoryview_from_NULL_pointer", make_memoryview_from_NULL_pointer,
|
||||||
METH_NOARGS},
|
METH_NOARGS},
|
||||||
|
{"buffer_fill_info", buffer_fill_info, METH_VARARGS},
|
||||||
{"crash_no_current_thread", crash_no_current_thread, METH_NOARGS},
|
{"crash_no_current_thread", crash_no_current_thread, METH_NOARGS},
|
||||||
{"test_current_tstate_matches", test_current_tstate_matches, METH_NOARGS},
|
{"test_current_tstate_matches", test_current_tstate_matches, METH_NOARGS},
|
||||||
{"run_in_subinterp", run_in_subinterp, METH_VARARGS},
|
{"run_in_subinterp", run_in_subinterp, METH_VARARGS},
|
||||||
|
|
|
@ -767,11 +767,17 @@ PyBuffer_FillInfo(Py_buffer *view, PyObject *obj, void *buf, Py_ssize_t len,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((flags & PyBUF_WRITABLE) == PyBUF_WRITABLE) &&
|
if (flags != PyBUF_SIMPLE) { /* fast path */
|
||||||
(readonly == 1)) {
|
if (flags == PyBUF_READ || flags == PyBUF_WRITE) {
|
||||||
PyErr_SetString(PyExc_BufferError,
|
PyErr_BadInternalCall();
|
||||||
"Object is not writable.");
|
return -1;
|
||||||
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);
|
view->obj = Py_XNewRef(obj);
|
||||||
|
|
Loading…
Reference in New Issue