-
Notifications
You must be signed in to change notification settings - Fork 13k
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
remove the memcpy-on-equal-ptrs assumption #118265
Conversation
r? @cuviper (rustbot has picked a reviewer for you, use r? to override) |
A black swan has not been observed, therefore all swans are white? Or do we have stronger confirmation that LLVM won't do this? |
I didn't say it's great but I don't know any better way than asking @nikic. 🤷 LLVM does not even document anywhere what it assumes about the libc That said, the main reason I am proposing this is that if we do see a black swan, then the bit of text we have here doesn't actually help. We are unsound on musl. So I want to have the text removed from the docs to make it clear that this would be a soundness bug. |
In the
|
Looks like rustc indeed emits |
Our semantics for Basically, if the assignment is of a type with |
The MIR we generate has a temporary. This gets turned into LLVM IR with two memcpy to and from the temporary, which apparently LLVM optimizes into a memmove that skips the temporary. So all is good, as far as I can see. |
//! source and target pointer are equal, the function is assumed to not be UB. | ||
//! (Note that these are standard assumptions among compilers: | ||
//! the `n` parameter is 0, the function is assumed to not be UB, even if the pointers are NULL or | ||
//! dangling. (Note that making extra assumptions about these functions is common among compilers: |
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.
While removing the "equal" part, you added "NULL or dangling" -- isn't that a new assumption? Or are we already living by that elsewhere?
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.
That's a clarification. We already have "if the n parameter is 0, the function is assumed to not be UB", which was already meant to include all pointers, including NULL or dangling. I just made it more explicit.
@bors r+ rollup |
…iaskrgr Rollup of 7 pull requests Successful merges: - rust-lang#116839 (Implement thread parking for xous) - rust-lang#118265 (remove the memcpy-on-equal-ptrs assumption) - rust-lang#118269 (Unify `TraitRefs` and `PolyTraitRefs` in `ValuePairs`) - rust-lang#118394 (Remove HIR opkinds) - rust-lang#118398 (Add proper cfgs in std) - rust-lang#118419 (Eagerly return `ExprKind::Err` on `yield`/`await` in wrong coroutine context) - rust-lang#118422 (Fix coroutine validation for mixed panic strategy) r? `@ghost` `@rustbot` modify labels: rollup
…iaskrgr Rollup of 7 pull requests Successful merges: - rust-lang#116839 (Implement thread parking for xous) - rust-lang#118265 (remove the memcpy-on-equal-ptrs assumption) - rust-lang#118269 (Unify `TraitRefs` and `PolyTraitRefs` in `ValuePairs`) - rust-lang#118394 (Remove HIR opkinds) - rust-lang#118398 (Add proper cfgs in std) - rust-lang#118419 (Eagerly return `ExprKind::Err` on `yield`/`await` in wrong coroutine context) - rust-lang#118422 (Fix coroutine validation for mixed panic strategy) r? `@ghost` `@rustbot` modify labels: rollup
Rollup merge of rust-lang#118265 - RalfJung:memcpy, r=cuviper remove the memcpy-on-equal-ptrs assumption One of the libc we support, musl, [defines `memcpy` with `restrict` pointers](https://git.musl-libc.org/cgit/musl/tree/src/string/memcpy.c#n5). This in fact matches the definition in the C standard. Calling that `memcpy` with overlapping pointers is clearly UB, who knows what the compiler did when optimizing this `memcpy` -- it certainly assumed source and destination to be disjoint. Lucky enough, it does not seem like we actually need this assumption that `memcpy(p, p, n)` is always allowed. clang and GCC need it since they use `memcpy` to compile C assignments, but [we use memmove for similar code](https://godbolt.org/z/bcW85WYcM). There are no known cases where LLVM introduces calls to memcpy on equal pointers itself. (And if there were, that would be a soundness bug in rustc due to the musl issue mentioned above.) This does mean we must make sure to never call the LLVM `memcpy` builtin on equal ranges even though the LangRef says that is allowed. Currently that is the case so we just need to make sure it remains the case. :) Cc `@rust-lang/opsem` `@rust-lang/wg-llvm`
One of the libc we support, musl, defines
memcpy
withrestrict
pointers. This in fact matches the definition in the C standard. Calling thatmemcpy
with overlapping pointers is clearly UB, who knows what the compiler did when optimizing thismemcpy
-- it certainly assumed source and destination to be disjoint.Lucky enough, it does not seem like we actually need this assumption that
memcpy(p, p, n)
is always allowed. clang and GCC need it since they usememcpy
to compile C assignments, but we use memmove for similar code. There are no known cases where LLVM introduces calls to memcpy on equal pointers itself. (And if there were, that would be a soundness bug in rustc due to the musl issue mentioned above.)This does mean we must make sure to never call the LLVM
memcpy
builtin on equal ranges even though the LangRef says that is allowed. Currently that is the case so we just need to make sure it remains the case. :) Cc @rust-lang/opsem @rust-lang/wg-llvm