Skip to content

fix(rust): release ManagedStatement once via Arc inner Drop - #36

Open
fornwall wants to merge 1 commit into
mainfrom
fix/rust-managed-statement-double-free
Open

fix(rust): release ManagedStatement once via Arc inner Drop#36
fornwall wants to merge 1 commit into
mainfrom
fix/rust-managed-statement-double-free

Conversation

@fornwall

Copy link
Copy Markdown
Owner

The bug

ManagedStatement derives Clone and wraps an Arc<ManagedStatementInner>, but the Drop impl lived on ManagedStatement itself and called the driver's StatementRelease on every drop. Because the handle is Clone + Arc, cloning and then dropping released the shared FFI statement more than once — a double-free across the C ABI — and left any surviving clones operating on an already-released statement (use-after-release).

The fix

Move the Drop impl from ManagedStatement onto the Arc-wrapped inner struct ManagedStatementInner, so StatementRelease runs exactly once when the last Arc is dropped. This mirrors the existing, correct pattern used by ManagedConnectionInner and ManagedDatabaseInner. The driver is reached through the connection chain (self.connection.database.driver.driver), and the existing TODO about handling StatementRelease failure is preserved.

Verification

  • cargo build -p adbc_driver_manager — succeeds
  • cargo test -p adbc_driver_manager --lib — 18 passed, 0 failed, 13 ignored

🤖 Generated with Claude Code

https://claude.ai/code/session_01XNCrC87g9MkppGpL4MDgh5

ManagedStatement is Clone and wraps an Arc<ManagedStatementInner>, but the
Drop impl lived on ManagedStatement itself, calling the driver's
StatementRelease on every drop. Cloning then dropping the handle released
the shared FFI statement more than once (double-free) and left surviving
clones operating on a released statement (use-after-release).

Move Drop onto ManagedStatementInner, the Arc-wrapped inner struct, so
StatementRelease runs exactly once when the last Arc drops. This mirrors
how ManagedConnectionInner and ManagedDatabaseInner already handle release.
The driver is reached through the connection chain
(self.connection.database.driver.driver).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XNCrC87g9MkppGpL4MDgh5
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.

1 participant