Description
The following program fails to run in Miri with an unaligned memory access:
use rand::Rng;
fn main()
{
let mut rng = rand::thread_rng();
let _val = rng.gen::<i32>();
let _val = rng.gen::<usize>(); // causes unaligned memory access
}
This is caused by this line of code:
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 with read_unaligned
and write_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?