]> granicus.if.org Git - python/commitdiff
Issue #14203: Remove obsolete support for view==NULL in bytesiobuf_getbuffer()
authorStefan Krah <skrah@bytereef.org>
Tue, 3 Feb 2015 20:43:23 +0000 (21:43 +0100)
committerStefan Krah <skrah@bytereef.org>
Tue, 3 Feb 2015 20:43:23 +0000 (21:43 +0100)
and array_buffer_getbuf().

Lib/test/test_array.py
Lib/test/test_bytes.py
Misc/NEWS
Modules/_io/bytesio.c
Modules/_testcapimodule.c
Modules/arraymodule.c

index adb0fd37ccff7c16a6594b98ff9b4923b76a6c4d..10d99462fd8701491065c7cc1008938f5ab45c2b 100644 (file)
@@ -1041,6 +1041,11 @@ class BaseTest:
             a = array.array(self.typecode, "foo")
             a = array.array(self.typecode, array.array('u', 'foo'))
 
+    @support.cpython_only
+    def test_obsolete_write_lock(self):
+        from _testcapi import getbuffer_with_null_view
+        a = array.array('B', b"")
+        self.assertRaises(BufferError, getbuffer_with_null_view, a)
 
 class StringTest(BaseTest):
 
index a66a9822055d6e8b374fb86980a5804b86950d34..a9f64a0dccbcb44da70941f511955f233a66e4da 100644 (file)
@@ -1224,6 +1224,10 @@ class ByteArrayTest(BaseBytesTest, unittest.TestCase):
         self.assertRaises(BufferError, delslice)
         self.assertEqual(b, orig)
 
+    @test.support.cpython_only
+    def test_obsolete_write_lock(self):
+        from _testcapi import getbuffer_with_null_view
+        self.assertRaises(BufferError, getbuffer_with_null_view, bytearray())
 
 class AssortedBytesTest(unittest.TestCase):
     #
index c0ec17437691784c6cc9b364acdc3c4c057f4ce6..4fcee12d008d27b334bb784e74748d3f89611b13 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -1560,9 +1560,9 @@ Build
 C API
 -----
 
-- Issue #14203: Remove obsolete support for view==NULL in PyBuffer_FillInfo()
-  and bytearray_getbuffer().  Both functions now raise BufferError in that
-  case.
+- Issue #14203: Remove obsolete support for view==NULL in PyBuffer_FillInfo(),
+  bytearray_getbuffer(), bytesiobuf_getbuffer() and array_buffer_getbuf().
+  All functions now raise BufferError in that case.
 
 - Issue #22445: PyBuffer_IsContiguous() now implements precise contiguity
   tests, compatible with NumPy's NPY_RELAXED_STRIDES_CHECKING compilation
index 0a272ecc7ae5045b0e86cf9908296eb97a0e3ce3..fc4ea74b23f370055db474ec26213319dacce33e 100644 (file)
@@ -1028,23 +1028,24 @@ PyTypeObject PyBytesIO_Type = {
 static int
 bytesiobuf_getbuffer(bytesiobuf *obj, Py_buffer *view, int flags)
 {
-    int ret;
     bytesio *b = (bytesio *) obj->source;
+
+    if (view == NULL) {
+        PyErr_SetString(PyExc_BufferError,
+            "bytesiobuf_getbuffer: view==NULL argument is obsolete");
+        return -1;
+    }
     if (SHARED_BUF(b)) {
         if (unshare_buffer(b, b->string_size) < 0)
             return -1;
     }
-    if (view == NULL) {
-        b->exports++;
-        return 0;
-    }
-    ret = PyBuffer_FillInfo(view, (PyObject*)obj,
+
+    /* cannot fail if view != NULL and readonly == 0 */
+    (void)PyBuffer_FillInfo(view, (PyObject*)obj,
                             PyBytes_AS_STRING(b->buf), b->string_size,
                             0, flags);
-    if (ret >= 0) {
-        b->exports++;
-    }
-    return ret;
+    b->exports++;
+    return 0;
 }
 
 static void
index 3cbe00cd9654c64fd5999757d65c6aea3d24b77f..a4930fbc8f843621945c9eb212c997c4118f4766 100644 (file)
@@ -2518,21 +2518,26 @@ test_from_contiguous(PyObject* self, PyObject *noargs)
 
     Py_RETURN_NONE;
 }
+
+extern PyTypeObject _PyBytesIOBuffer_Type;
+
 static PyObject *
 test_pep3118_obsolete_write_locks(PyObject* self, PyObject *noargs)
 {
+    PyTypeObject *type = &_PyBytesIOBuffer_Type;
     PyObject *b;
     char *dummy[1];
     int ret, match;
 
+    /* PyBuffer_FillInfo() */
     ret = PyBuffer_FillInfo(NULL, NULL, dummy, 1, 0, PyBUF_SIMPLE);
     match = PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_BufferError);
     PyErr_Clear();
     if (ret != -1 || match == 0)
         goto error;
 
-    b = PyByteArray_FromStringAndSize("", 0);
+    /* bytesiobuf_getbuffer() */
+    b = type->tp_alloc(type, 0);
     if (b == NULL) {
         return NULL;
     }
@@ -2552,6 +2557,18 @@ error:
     return NULL;
 }
 
+/* This tests functions that historically supported write locks.  It is
+   wrong to call getbuffer() with view==NULL and a compliant getbufferproc
+   is entitled to segfault in that case. */
+static PyObject *
+getbuffer_with_null_view(PyObject* self, PyObject *obj)
+{
+    if (PyObject_GetBuffer(obj, NULL, PyBUF_SIMPLE) < 0)
+        return NULL;
+
+    Py_RETURN_NONE;
+}
+
 /* Test that the fatal error from not having a current thread doesn't
    cause an infinite loop.  Run via Lib/test/test_capi.py */
 static PyObject *
@@ -3213,6 +3230,7 @@ static PyMethodDef TestMethods[] = {
     {"test_capsule", (PyCFunction)test_capsule, METH_NOARGS},
     {"test_from_contiguous", (PyCFunction)test_from_contiguous, METH_NOARGS},
     {"test_pep3118_obsolete_write_locks", (PyCFunction)test_pep3118_obsolete_write_locks, METH_NOARGS},
+    {"getbuffer_with_null_view", getbuffer_with_null_view, METH_O},
     {"getargs_tuple",           getargs_tuple,                   METH_VARARGS},
     {"getargs_keywords", (PyCFunction)getargs_keywords,
       METH_VARARGS|METH_KEYWORDS},
index 87bdb2c813d7b52bb1796e6f9d8487cf9766b40b..6e755f4fcfa22c7bac13c2f03a080874d7b81c0d 100644 (file)
@@ -2530,7 +2530,11 @@ static const void *emptybuf = "";
 static int
 array_buffer_getbuf(arrayobject *self, Py_buffer *view, int flags)
 {
-    if (view==NULL) goto finish;
+    if (view == NULL) {
+        PyErr_SetString(PyExc_BufferError,
+            "array_buffer_getbuf: view==NULL argument is obsolete");
+        return -1;
+    }
 
     view->buf = (void *)self->ob_item;
     view->obj = (PyObject*)self;
@@ -2560,7 +2564,6 @@ array_buffer_getbuf(arrayobject *self, Py_buffer *view, int flags)
 #endif
     }
 
- finish:
     self->ob_exports++;
     return 0;
 }