-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor miri pointer checks #62081
Refactor miri pointer checks #62081
Conversation
… one function: memory.check_ptr_access That function also takes care of converting a Scalar to a Pointer, should that be needed. Not all accesses need that though: if the access has size 0, None is returned. Everyone accessing memory based on a Scalar should use this method to get the Pointer they need. All operations on the Allocation work on Pointer inputs and expect all the checks to have happened (and will ICE if the bounds are violated). The operations on Memory work on Scalar inputs and do the checks themselves. The only other public method to check pointers is memory.ptr_may_be_null, which is needed in a few places. With this, we can make all the other methods (tests for a pointer being in-bounds and checking alignment) private helper methods, used to implement the two public methods. That maks the public API surface much easier to use and harder to mis-use. While I am at it, this also removes the assumption that the vtable part of a `dyn Trait`-fat-pointer is a `Pointer` (as opposed to a pointer cast to an integer, stored as raw bits).
…eck for fn allocations
The Miri side of this is at rust-lang/miri#787. |
// The biggest power of two through which `offset` is divisible. | ||
let offset_pow2 = 1 << offset.trailing_zeros(); | ||
err!(AlignmentCheckFailed { | ||
has: Align::from_bytes(offset_pow2).unwrap(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The old code used offset % align.bytes()
as has
, but I think that's just wrong. In fact it's not even always a power of 2, so there could be ICEs there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yes, here is the ICE (run that in Miri): https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=ff9f736de49ff1a905ba8e512e258904
r=me with typo nit (multiple occurrences) fixed or not |
@bors r=oli-obk |
📌 Commit 7e83028 has been approved by |
Refactor miri pointer checks Centralize bounds, alignment and NULL checking for memory accesses in one function: `memory.check_ptr_access`. That function also takes care of converting a `Scalar` to a `Pointer`, should that be needed. Not all accesses need that though: if the access has size 0, `None` is returned. Everyone accessing memory based on a `Scalar` should use this method to get the `Pointer` they need. All operations on the `Allocation` work on `Pointer` inputs and expect all the checks to have happened (and will ICE if the bounds are violated). The operations on `Memory` work on `Scalar` inputs and do the checks themselves. The only other public method to check pointers is `memory.ptr_may_be_null`, which is needed in a few places. No need for `check_align` or similar methods. That makes the public API surface much easier to use and harder to mis-use. This should be largely no-functional-change, except that ZST accesses to a "true" pointer that is dangling or out-of-bounds are now considered UB. This is to be conservative wrt. whatever LLVM might be doing. While I am at it, this also removes the assumption that the vtable part of a `dyn Trait`-fat-pointer is a `Pointer` (as opposed to a pointer cast to an integer, stored as raw bits). r? @oli-obk
☀️ Test successful - checks-travis, status-appveyor |
Tested on commit rust-lang/rust@7e08576. Direct link to PR: <rust-lang/rust#62081> 💔 miri on windows: test-pass → build-fail (cc @oli-obk @RalfJung @eddyb, @rust-lang/infra). 💔 miri on linux: test-pass → build-fail (cc @oli-obk @RalfJung @eddyb, @rust-lang/infra).
adjust for refactored memory pointer checks The Miri side of rust-lang/rust#62081.
Centralize bounds, alignment and NULL checking for memory accesses in one function:
memory.check_ptr_access
. That function also takes care of converting aScalar
to aPointer
, should that be needed. Not all accesses need that though: if the access has size 0,None
is returned. Everyone accessing memory based on aScalar
should use this method to get thePointer
they need.All operations on the
Allocation
work onPointer
inputs and expect all the checks to have happened (and will ICE if the bounds are violated). The operations onMemory
work onScalar
inputs and do the checks themselves.The only other public method to check pointers is
memory.ptr_may_be_null
, which is needed in a few places. No need forcheck_align
or similar methods. That makes the public API surface much easier to use and harder to mis-use.This should be largely no-functional-change, except that ZST accesses to a "true" pointer that is dangling or out-of-bounds are now considered UB. This is to be conservative wrt. whatever LLVM might be doing.
While I am at it, this also removes the assumption that the vtable part of a
dyn Trait
-fat-pointer is aPointer
(as opposed to a pointer cast to an integer, stored as raw bits).r? @oli-obk