fix(rust/ffi): preserve caller's AdbcError private_data on the 1.0.0 path#4473
Merged
Conversation
…path The FFI driver exporter wrote the entire FFI_AdbcError struct into the caller's out-pointer on every failed method, unconditionally clobbering the private_data (and, at two of the three sites, private_driver) fields. The AdbcError documentation in c/include/arrow-adbc/adbc.h says these fields exist only in the ADBC 1.1.0 layout and that a driver "should read/write these fields if and only if vendor_code is equal to ADBC_ERROR_VENDOR_CODE_PRIVATE_DATA", and "should never touch more than [the 1.0.0-sized] portion of an AdbcError struct" otherwise. Overwriting them corrupts memory an ADBC 1.0.0 caller owns (or does not have at all). Route all three error-writing sites (check_err!, pointer_as_mut! and the panic handler in catch_panic) through a new set_error_out() that: - reads the caller's vendor_code first; when it is not the sentinel, writes only the 1.0.0-sized prefix (message/vendor_code/sqlstate/release) and installs a message-only release, leaving private_data/private_driver as the caller set them; - otherwise behaves as before: preserves private_driver and writes the full struct, with structured details carried in private_data. This makes the C++ validation suite's StatementTest.ErrorCompatibility pass. Adds unit tests for both the opted-in and 1.0.0-compatible paths. Signed-off-by: Fredrik Fornwall <fredrik@fornwall.net>
d5cf695 to
75cab7d
Compare
lidavidm
approved these changes
Jul 8, 2026
lidavidm
left a comment
Member
There was a problem hiding this comment.
Thanks, I manually fixed up some things
fornwall
added a commit
to fornwall/adbc-spanner
that referenced
this pull request
Jul 9, 2026
…rorCompatibility (#190) apache/arrow-adbc#4473 (preserve the caller's AdbcError.private_data on the ADBC 1.0.0 path) has merged. Both prior fork fixes (#4469 rows_affected=-1 and the idempotent error release) are also upstream now, so the fornwall/arrow-adbc fork is redundant. Repoint adbc_core / adbc_ffi / adbc_driver_manager at apache/arrow-adbc main (198f39a, latest commit; 0.23 -> 0.24) and drop the fork. Still a git pin (these FFI fixes are not in a crates.io release yet), so it remains a publish blocker as before, just tracking upstream main. Enable SpannerStatementTest.ErrorCompatibility in the gated C++ validation allowlist — the test already existed in the 0.23 suite and was failing only because the old exporter clobbered private_data, which #4473 fixes. Verified: fmt/clippy/cargo test green; the gated C++ validation suite passes 43/43 against a throwaway emulator, including ErrorCompatibility. Claude-Session: https://claude.ai/code/session_012ezKKdkPyD5JeXgAnQ4Fgo Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Disclaimer: Most of this PR description and all the code here was AI generated. Let me know if there is any issues to dig into or modifications to be made. The code comments are rather verbose, but not obviously unnecessary - let me know if they should be removed/shortened.
The FFI driver exporter wrote the entire
FFI_AdbcErrorstruct into the caller's out-pointer on every failed method, unconditionally clobbering theprivate_data(and, at two of the three sites,private_driver) fields.The
AdbcErrordocumentation inc/include/arrow-adbc/adbc.hsays these fields exist only in the ADBC 1.1.0 layout and that a driver "should read/write these fields if and only if vendor_code is equal to ADBC_ERROR_VENDOR_CODE_PRIVATE_DATA", and "should never touch more than [the 1.0.0-sized] portion of an AdbcError struct" otherwise. Overwriting them corrupts memory an ADBC 1.0.0 caller owns (or does not have at all).Route all three error-writing sites (check_err!, pointer_as_mut! and the panic handler in catch_panic) through a new
set_error_out()that:vendor_codefirst; when it is not the sentinel, writes only the 1.0.0-sized prefix and installs a message-only release, leavingprivate_data/private_driveras the caller set them;private_driverand writes the full struct, with structured details carried inprivate_data.This makes the C++ validation suite's
StatementTest.ErrorCompatibilitypass against an ADBC driving implemented usingadbc_ffi.Fixes #4472.