Skip to content

fix(rust/ffi): preserve caller's AdbcError private_data on the 1.0.0 path#4473

Merged
lidavidm merged 3 commits into
apache:mainfrom
fornwall:fix-error-compatibility
Jul 8, 2026
Merged

fix(rust/ffi): preserve caller's AdbcError private_data on the 1.0.0 path#4473
lidavidm merged 3 commits into
apache:mainfrom
fornwall:fix-error-compatibility

Conversation

@fornwall

@fornwall fornwall commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

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_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 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 against an ADBC driving implemented using adbc_ffi.

Fixes #4472.

@fornwall fornwall requested a review from wjones127 as a code owner July 7, 2026 19:48
…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>
@fornwall fornwall force-pushed the fix-error-compatibility branch from d5cf695 to 75cab7d Compare July 8, 2026 00:22

@lidavidm lidavidm left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I manually fixed up some things

@lidavidm lidavidm merged commit 732726e into apache:main Jul 8, 2026
18 of 19 checks passed
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

abdc_ffi: The rust FFI driver exporter clobbers private_data and private_driver

2 participants