Skip to content

Commit b3a9c44

Browse files
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 <283775510+carrerasdarren-cell@users.noreply.github.com> Signed-off-by: Raúl Cumplido <raulcumplido@gmail.com>
1 parent 0d8f1b9 commit b3a9c44

2 files changed

Lines changed: 9 additions & 0 deletions

File tree

‎python/pyarrow/io.pxi‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -548,6 +548,8 @@ cdef class NativeFile(_Weakrefable):
548548
handle = self.get_input_stream()
549549

550550
py_buf = py_buffer(b)
551+
if not py_buf.buffer.get().is_mutable():
552+
raise TypeError("readinto() argument must be a writable buffer")
551553
buf_len = py_buf.size
552554
buf = py_buf.buffer.get().mutable_data()
553555

‎python/pyarrow/tests/test_io.py‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,6 +1024,13 @@ def test_nativefile_write_memoryview():
10241024
assert buf.to_pybytes() == data * 3
10251025

10261026

1027+
@pytest.mark.parametrize("dst_buf", [b"a", memoryview(b"a")])
1028+
def test_native_file_readinto_rejects_readonly_buffer(dst_buf):
1029+
with pa.BufferReader(b"x") as f:
1030+
with pytest.raises(TypeError, match="writable buffer"):
1031+
f.readinto(dst_buf)
1032+
1033+
10271034
# ----------------------------------------------------------------------
10281035
# Mock output stream
10291036

0 commit comments

Comments
 (0)