This is an automated email from the ASF dual-hosted git repository.
AlenkaF 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 8c7b08f4269 GH-51041: [Python] Reject non-Buffer
FunctionOptions.deserialize input (#51129)
8c7b08f4269 is described below
commit 8c7b08f42694342ed1dbe7e8a351a947dae8e13d
Author: Stefan Wang <[email protected]>
AuthorDate: Thu Sep 10 01:15:53 2026 -0700
GH-51041: [Python] Reject non-Buffer FunctionOptions.deserialize input
(#51129)
### Rationale for this change
Calling `pyarrow.compute.FunctionOptions.deserialize()` with anything that
is not a `Buffer` crashes the interpreter. `None`, an `int`, a `list` and a
`bytes` object all segfault, so a caller who passes the wrong object, or who
forwards an unvalidated value, loses the process rather than seeing an
exception.
`deserialize()` hands its argument to `pyarrow_unwrap_buffer()`, which
returns a null pointer for a non-`Buffer`. The `deref()` on the next line then
dereferences null.
Before this change the call terminates the process. After it, the call
raises `TypeError` naming the type it received.
### What changes are included in this PR?
The static method now declares its parameter as `Buffer buf not None`,
which is what its docstring already says it takes. Cython rejects a wrong type
before the unwrap runs, so the null pointer is never produced.
### Are these changes tested?
Yes, by a parametrized case over the four inputs above.
<details>
<summary>Red, with this commit's source file reverted to its
parent</summary>
```console
$ git checkout HEAD~1 python/pyarrow/_compute.pyx
$ pip install -e python --no-build-isolation
$ python -X faulthandler -c "import pyarrow.compute as pc;
pc.FunctionOptions.deserialize(None)"
Fatal Python error: Segmentation fault
Current thread 0x00000001f6fbe180 (most recent call first):
File "<string>", line 1 in <module>
Extension modules: numpy._core._multiarray_umath,
numpy.linalg._umath_linalg, pyarrow.lib, pyarrow._compute (total: 4)
```
The same crash occurs for `1`, `[]` and `b''`.
</details>
<details>
<summary>Green, with the fix applied</summary>
```console
$ git checkout HEAD -- python/pyarrow/_compute.pyx
$ pip install -e python --no-build-isolation
$ python -m pytest pyarrow/tests/test_compute.py -k
deserialize_rejects_non_buffers -v
collected 607 items / 603 deselected / 4 selected
pyarrow/tests/test_compute.py::test_function_options_deserialize_rejects_non_buffers[None]
PASSED [ 25%]
pyarrow/tests/test_compute.py::test_function_options_deserialize_rejects_non_buffers[1]
PASSED [ 50%]
pyarrow/tests/test_compute.py::test_function_options_deserialize_rejects_non_buffers[value2]
PASSED [ 75%]
pyarrow/tests/test_compute.py::test_function_options_deserialize_rejects_non_buffers[]
PASSED [100%]
====================== 4 passed, 603 deselected in 0.06s
=======================
```
```console
$ for v in None 1 "[]" "b''"; do python -c "
import pyarrow.compute as pc
try:
pc.FunctionOptions.deserialize($v)
except TypeError as e:
print('$v', '->', e)
"; done
None -> Argument 'buf' has incorrect type (expected pyarrow.lib.Buffer, got
NoneType)
1 -> Argument 'buf' has incorrect type (expected pyarrow.lib.Buffer, got
int)
[] -> Argument 'buf' has incorrect type (expected pyarrow.lib.Buffer, got
list)
b -> Argument 'buf' has incorrect type (expected pyarrow.lib.Buffer, got
bytes)
```
</details>
A valid buffer still round-trips, and the rest of `test_compute.py` is
unaffected.
<details>
<summary>Round-trip and full suite</summary>
```console
$ python -c "import pyarrow.compute as pc; o =
pc.ArraySortOptions(order='descending');
print(pc.FunctionOptions.deserialize(o.serialize()) == o)"
True
$ python -m pytest pyarrow/tests/test_compute.py -q
584 passed, 23 skipped, 11 warnings in 3.09s
```
</details>
### Are there any user-facing changes?
Passing a non-`Buffer` to `FunctionOptions.deserialize()` now raises
`TypeError` instead of terminating the process. Callers already passing a
`Buffer`, which is what the docstring documents, are unaffected.
* GitHub Issue: #51041
Authored-by: 1fanwang <[email protected]>
Signed-off-by: AlenkaF <[email protected]>
---
python/pyarrow/_compute.pyx | 2 +-
python/pyarrow/tests/test_compute.py | 6 ++++++
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/python/pyarrow/_compute.pyx b/python/pyarrow/_compute.pyx
index 1c98bbfdea2..da237d99fd5 100644
--- a/python/pyarrow/_compute.pyx
+++ b/python/pyarrow/_compute.pyx
@@ -630,7 +630,7 @@ cdef class FunctionOptions(_Weakrefable):
return pyarrow_wrap_buffer(c_buf)
@staticmethod
- def deserialize(buf):
+ def deserialize(Buffer buf not None):
"""
Deserialize options for a function.
diff --git a/python/pyarrow/tests/test_compute.py
b/python/pyarrow/tests/test_compute.py
index 8b2ad2b333f..6fac20a5ada 100644
--- a/python/pyarrow/tests/test_compute.py
+++ b/python/pyarrow/tests/test_compute.py
@@ -241,6 +241,12 @@ def test_option_class_equality(request):
"ArraySortOptions(order=Ascending, null_placement=AtEnd)"
[email protected]("value", [None, 1, [], b""])
+def test_function_options_deserialize_rejects_non_buffers(value):
+ with pytest.raises(TypeError):
+ pc.FunctionOptions.deserialize(value)
+
+
def test_list_functions():
assert len(pc.list_functions()) > 10
assert "add" in pc.list_functions()