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

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


The following commit(s) were added to refs/heads/main by this push:
     new b3a9c444471 GH-51044: [Python] Reject read-only readinto destinations 
(#51126)
b3a9c444471 is described below

commit b3a9c4444712046a2608aed174ccb79ca05c51bc
Author: carrerasdarren-cell <[email protected]>
AuthorDate: Wed Sep 9 05:59:59 2026 -0400

    GH-51044: [Python] Reject read-only readinto destinations (#51126)
    
    ### Rationale for this change
    
    `BufferReader.readinto()` currently segfaults when passed a read-only 
destination such as `bytes` or a read-only `memoryview`. `py_buffer()` creates 
an immutable Arrow buffer, `mutable_data()` returns a null pointer, and the C++ 
read path attempts to copy into that pointer. A Python API misuse should raise 
a Python exception rather than terminate the interpreter.
    
    ### What changes are included in this PR?
    
    - Validate that a `NativeFile.readinto()` destination is mutable before 
obtaining its writable pointer.
    - Raise `TypeError` for immutable destinations.
    - Add regression coverage for `bytes` and read-only `memoryview` 
destinations.
    
    ### Are these changes tested?
    
    Yes. The focused `readinto` tests pass against a locally compiled patched 
`pyarrow.lib`. The stock 25.0.1 wheel exits with status 139 for the issue 
reproducer, while the patched build raises the expected `TypeError`; the 
writable `bytearray` control continues to read successfully.
    
    ### Are there any user-facing changes?
    
    Yes. Passing a read-only destination to `NativeFile.readinto()` now raises 
`TypeError` instead of terminating the interpreter. Writable-buffer behavior is 
unchanged.
    
    Fixes #51044.
    
    This contribution was developed with assistance from OpenAI Codex. I 
reviewed, tested, and take responsibility for the patch and this description.
    
    * GitHub Issue: #51044
    
    Authored-by: Darren Carreras 
<[email protected]>
    Signed-off-by: Raúl Cumplido <[email protected]>
---
 python/pyarrow/io.pxi           | 2 ++
 python/pyarrow/tests/test_io.py | 7 +++++++
 2 files changed, 9 insertions(+)

diff --git a/python/pyarrow/io.pxi b/python/pyarrow/io.pxi
index b648fbf6698..32f7bc26b1f 100644
--- a/python/pyarrow/io.pxi
+++ b/python/pyarrow/io.pxi
@@ -548,6 +548,8 @@ cdef class NativeFile(_Weakrefable):
         handle = self.get_input_stream()
 
         py_buf = py_buffer(b)
+        if not py_buf.buffer.get().is_mutable():
+            raise TypeError("readinto() argument must be a writable buffer")
         buf_len = py_buf.size
         buf = py_buf.buffer.get().mutable_data()
 
diff --git a/python/pyarrow/tests/test_io.py b/python/pyarrow/tests/test_io.py
index 8494a0ee66b..2cebaabbcbd 100644
--- a/python/pyarrow/tests/test_io.py
+++ b/python/pyarrow/tests/test_io.py
@@ -1024,6 +1024,13 @@ def test_nativefile_write_memoryview():
     assert buf.to_pybytes() == data * 3
 
 
[email protected]("dst_buf", [b"a", memoryview(b"a")])
+def test_native_file_readinto_rejects_readonly_buffer(dst_buf):
+    with pa.BufferReader(b"x") as f:
+        with pytest.raises(TypeError, match="writable buffer"):
+            f.readinto(dst_buf)
+
+
 # ----------------------------------------------------------------------
 # Mock output stream
 

Reply via email to