-
Notifications
You must be signed in to change notification settings - Fork 432
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
rand performs unaligned memory access (and invalid raw ptr usage) #779
Comments
|
Thanks @RalfJung; some good questions here. This particular example is around 13% faster with the HC128 generator on my system ( Following your suggestions, I get around the same performance with this version of the code: if cfg!(any(target_arch = "x86", target_arch = "x86_64")) {
// requires little-endian CPU supporting unaligned reads:
let ptr: *const u64 = &results[index..index+1] as *const [u32] as *const u32 as *const u64;
unsafe { read_unaligned(ptr) }
} Is this acceptable in your opinion? Knowing where to draw the line between The same performance observations appear to apply to the Of note is that |
This looks good, I'll try to run it in Miri as well. Do you have this in a branch somewhere?
That's in fact how I noticed, as you can see from my example above. I should probably try to run the entire rand test suite in Miri... will it exercise all these code paths irrespective of what |
I can confirm that RalfJung@8303309 makes my small tests pass in Miri. |
Running the entire test suite should probably cover most of the Thanks again for stepping in to fix the |
I'm afraid the Lines 234 to 237 in 9828cdf
and then passes that to generate . References must always be aligned even if they are not used.
So to fix this, |
Here, I'm not sure how important the direct copy is to performance (it's only going to be encountered with large fill requests), hence we could refactor this to generate to the Refactoring the trait isn't completely out of the question (it doesn't have a massive number of users), but I don't wish to force block RNG implementations to use ugly unsafe code, therefore would prefer |
bump rand in libcore/liballoc test suites This pulls in the fix for rust-random/rand#779, which trips Miri when running these test suites. `SmallRng` (formerly used by libcore) is no longer built by default, it needs a feature gate. I opted to switch to `StdRng` instead. Or should I enable the feature gate?
bump rand in libcore/liballoc test suites This pulls in the fix for rust-random/rand#779, which trips Miri when running these test suites. `SmallRng` (formerly used by libcore) is no longer built by default, it needs a feature gate. I opted to switch to `StdRng` instead. Or should I enable the feature gate?
bump rand in libcore/liballoc test suites This pulls in the fix for rust-random/rand#779, which trips Miri when running these test suites. `SmallRng` (formerly used by libcore) is no longer built by default, it needs a feature gate. I opted to switch to `StdRng` instead. Or should I enable the feature gate?
bump rand in libcore/liballoc test suites This pulls in the fix for rust-random/rand#779, which trips Miri when running these test suites. `SmallRng` (formerly used by libcore) is no longer built by default, it needs a feature gate. I opted to switch to `StdRng` instead. Or should I enable the feature gate?
The following program fails to run in Miri with an unaligned memory access:
This is caused by this line of code:
rand/rand_core/src/block.rs
Line 186 in 852988b
That casts a 4-aligned pointer to a
*const i64
and then uses that for a read.i64
reads must be 8-aligned. There is a comment in the souce indicating that this "requires little-endian CPU supporting unaligned reads", but that is not sufficient: the alignment requirement is made by LLVM, not by the CPU. In Rust, all accesses must be aligned on all platforms, no matter what the CPU says; any unaligned access causes UB (on all platforms). Unaligned accesses are only allowed withread_unaligned
andwrite_unaligned
.There is another problem with this code as well: It violates pointer provenance rules.
&results[index] as *const u32
creates a raw pointer that may be used to access this particular element, but it is not legal to use this pointer to access neighboring elements that were never cast to a raw pointer. You could try to fix this with something like&results[index..index+1] as *const [u32] as *const u32 as *const u64
.Is the performance of the "fallback code path" really so much worse that all these hacks are worth it?
The text was updated successfully, but these errors were encountered: