This is an automated email from the ASF dual-hosted git repository.
lidavidm pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-adbc.git
The following commit(s) were added to refs/heads/main by this push:
new 74e826061 fix(python/adbc_driver_manager): prevent segfault in
`_AdbcErrorHelper.check_error` (#4367)
74e826061 is described below
commit 74e826061087ce8e89e33e4e2e86efb2867583db
Author: Rishav Rungta <[email protected]>
AuthorDate: Fri Jun 12 12:18:04 2026 +0530
fix(python/adbc_driver_manager): prevent segfault in
`_AdbcErrorHelper.check_error` (#4367)
Closes https://github.com/apache/arrow-adbc/issues/4363
## Fix
Null-check `c_stream.release` in `_AdbcErrorHelper.check_error` itself.
If the stream was already released by PyArrow, re-raise the original
exception directly instead of calling `PyAdbcErrorFromArrayStream` on
dangling memory. This protects all callers, not just `_import_from_c`.
---------
Co-authored-by: David Li <[email protected]>
---
.../adbc_driver_manager/adbc_driver_manager/_reader.pyi | 3 +++
.../adbc_driver_manager/adbc_driver_manager/_reader.pyx | 3 +++
python/adbc_driver_manager/tests/test_reader.py | 16 ++++++++++++++++
3 files changed, 22 insertions(+)
diff --git a/python/adbc_driver_manager/adbc_driver_manager/_reader.pyi
b/python/adbc_driver_manager/adbc_driver_manager/_reader.pyi
index 48fc718dd..44b9df93e 100644
--- a/python/adbc_driver_manager/adbc_driver_manager/_reader.pyi
+++ b/python/adbc_driver_manager/adbc_driver_manager/_reader.pyi
@@ -32,3 +32,6 @@ class AdbcRecordBatchReader(pyarrow.RecordBatchReader):
def __enter__(self) -> AdbcRecordBatchReader: ...
def __exit__(self, type, value, traceback) -> None: ...
def __iter__(self) -> typing.Iterator[pyarrow.RecordBatch]: ...
+
+class _AdbcErrorHelper:
+ def check_error(self, exception: Exception) -> None: ...
diff --git a/python/adbc_driver_manager/adbc_driver_manager/_reader.pyx
b/python/adbc_driver_manager/adbc_driver_manager/_reader.pyx
index 43c5f9870..847f7ca1a 100644
--- a/python/adbc_driver_manager/adbc_driver_manager/_reader.pyx
+++ b/python/adbc_driver_manager/adbc_driver_manager/_reader.pyx
@@ -30,6 +30,9 @@ cdef class _AdbcErrorHelper:
CArrowArrayStream c_stream
def check_error(self, exception):
+ if self.c_stream.release == NULL:
+ raise exception
+
cdef:
CAdbcStatusCode c_status = ADBC_STATUS_OK
const CAdbcError* error = \
diff --git a/python/adbc_driver_manager/tests/test_reader.py
b/python/adbc_driver_manager/tests/test_reader.py
index 0480a5a8e..75b00fbe3 100644
--- a/python/adbc_driver_manager/tests/test_reader.py
+++ b/python/adbc_driver_manager/tests/test_reader.py
@@ -78,3 +78,19 @@ def test_reader_methods() -> None:
with _make_reader() as reader:
assert reader.schema == schema
+
+
+def test_check_error_with_released_stream():
+ """check_error must re-raise when c_stream.release is NULL."""
+ from adbc_driver_manager._reader import _AdbcErrorHelper
+
+ # Default-constructed helper has a zeroed c_stream (release == NULL)
+ helper = _AdbcErrorHelper.__new__(_AdbcErrorHelper)
+
+ err = ValueError("upstream error")
+ with pytest.raises(ValueError, match="upstream error"):
+ helper.check_error(err)
+
+ err = pyarrow.ArrowInvalid("Invalid or unsupported format string:
'd:5,2,32'")
+ with pytest.raises(pyarrow.ArrowInvalid, match="unsupported format
string"):
+ helper.check_error(err)