Skip to content

rand performs unaligned memory access (and invalid raw ptr usage) #779

Closed
@RalfJung

Description

@RalfJung

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:

unsafe { *(&results[index] as *const u32 as *const u64) }

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?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions