fix(r_memory): gate speculative SEXP recovery under Miri (#63)#197
Open
fix(r_memory): gate speculative SEXP recovery under Miri (#63)#197
Conversation
`try_recover_r_sexp` probes whether a data pointer came from an R SEXP by subtracting the known SEXPREC header size and reading sxpinfo bits. For pointers that came from a Rust-allocated Arrow buffer rather than an R vector, the speculative pointer has no valid allocation provenance, so the 4-byte load is undefined behavior under Miri's Stacked / Tree Borrows model — even though it's defined at the hardware level (heap is contiguous mapped memory). This is the conservative-GC pattern: analogous to Boehm scanning the heap without knowing allocation origins. Per #63 the probe can't be removed without losing zero-copy Arrow→R round-trips, and there is no Rust-safe way to re-establish provenance for a pointer synthesized from user data. Instead, make the whole function a no-op under `#[cfg(miri)]`: return `None` immediately so callers fall through to the copy path, which is a valid alternative at every call site. Production behavior is unchanged; Miri goes clean. Expanded the doc comment to cover the provenance gap explicitly so future readers don't have to re-discover why the bare pointer read exists. Closes #63. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
e95cbc9 to
501257f
Compare
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.
Closes #63.
Summary
`try_recover_r_sexp` is a conservative-GC-style probe: it subtracts the known SEXPREC header size from a data pointer and reads `sxpinfo` bits to check whether the candidate address looks like a SEXP. For pointers that didn't come from an R SEXP (e.g. a Rust-allocated Arrow buffer), the speculative pointer has no valid allocation provenance — defined at the hardware level, undefined under Miri's Stacked / Tree Borrows model.
Per the issue, removing the probe would kill zero-copy Arrow→R round-trips, and there's no Rust-safe way to manufacture provenance for a pointer synthesized from user data. So: make the whole function a no-op under `#[cfg(miri)]`. Callers fall through to the copy path, which is always valid. Production behavior unchanged; Miri now runs clean on this path.
Also expanded the doc comment explicitly calling out the conservative-GC analogy and the provenance gap, so future readers don't have to re-derive it from the issue thread.
Test plan
No R wrapper / vendor impact — change is entirely in `miniextendr-api/src/r_memory.rs`.
Generated with Claude Code