You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by we...@apache.org on 2018/09/16 00:43:10 UTC

[arrow] branch master updated: ARROW-3228: [Python] Do not allow PyObject_GetBuffer to obtain non-readonly Py_buffer when pyarrow Buffer is not mutable

This is an automated email from the ASF dual-hosted git repository.

wesm pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/arrow.git


The following commit(s) were added to refs/heads/master by this push:
     new 4121c5a  ARROW-3228: [Python] Do not allow PyObject_GetBuffer to obtain non-readonly Py_buffer when pyarrow Buffer is not mutable
4121c5a is described below

commit 4121c5abe9e5ff852bc738b46c04d99132bced62
Author: Wes McKinney <we...@apache.org>
AuthorDate: Sat Sep 15 20:42:59 2018 -0400

    ARROW-3228: [Python] Do not allow PyObject_GetBuffer to obtain non-readonly Py_buffer when pyarrow Buffer is not mutable
    
    NumPy tries to obtain a writable buffer to determine mutability. This was passing silently:
    
    https://github.com/numpy/numpy/blob/e8d177f74adbe5c7630721a4ab3f20f58839ac99/numpy/core/src/multiarray/ctors.c#L3711
    
    Author: Wes McKinney <we...@apache.org>
    
    Closes #2567 from wesm/ARROW-3228 and squashes the following commits:
    
    95287e6ea <Wes McKinney> Raise exception when writable buffer requested by PyObject_GetBuffer when pyarrow.Buffer is not writable
---
 python/pyarrow/io.pxi           | 11 +++++++----
 python/pyarrow/tests/test_io.py | 11 +++++++++++
 2 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/python/pyarrow/io.pxi b/python/pyarrow/io.pxi
index e240b23..8414f07 100644
--- a/python/pyarrow/io.pxi
+++ b/python/pyarrow/io.pxi
@@ -821,6 +821,13 @@ cdef class Buffer:
             self.buffer.get().size())
 
     def __getbuffer__(self, cp.Py_buffer* buffer, int flags):
+        if self.buffer.get().is_mutable():
+            buffer.readonly = 0
+        else:
+            if flags & cp.PyBUF_WRITABLE:
+                raise BufferError("Writable buffer requested but Arrow "
+                                  "buffer was not mutable")
+            buffer.readonly = 1
         buffer.buf = <char *>self.buffer.get().data()
         buffer.format = 'b'
         buffer.internal = NULL
@@ -828,10 +835,6 @@ cdef class Buffer:
         buffer.len = self.size
         buffer.ndim = 1
         buffer.obj = self
-        if self.buffer.get().is_mutable():
-            buffer.readonly = 0
-        else:
-            buffer.readonly = 1
         buffer.shape = self.shape
         buffer.strides = self.strides
         buffer.suboffsets = NULL
diff --git a/python/pyarrow/tests/test_io.py b/python/pyarrow/tests/test_io.py
index 547dee3..c1a210d 100644
--- a/python/pyarrow/tests/test_io.py
+++ b/python/pyarrow/tests/test_io.py
@@ -450,6 +450,17 @@ def test_buffer_hashing():
         hash(pa.py_buffer(b'123'))
 
 
+def test_buffer_protocol_respects_immutability():
+    # ARROW-3228; NumPy's frombuffer ctor determines whether a buffer-like
+    # object is mutable by first attempting to get a mutable buffer using
+    # PyObject_FromBuffer. If that fails, it assumes that the object is
+    # immutable
+    a = b'12345'
+    arrow_ref = pa.py_buffer(a)
+    numpy_ref = np.frombuffer(arrow_ref, dtype=np.uint8)
+    assert not numpy_ref.flags.writeable
+
+
 def test_foreign_buffer():
     obj = np.array([1, 2], dtype=np.int32)
     addr = obj.__array_interface__["data"][0]