Random Number Generator @WaffleLapkin @BoxyUwU
use std::mem::MaybeUninit;
fn main() {
// Safety: all bitpatterns are valid for u8
let random_number: u8 = unsafe { MaybeUninit::uninit().assume_init() };
let very_random_number = if random_number <= 100 {
unsafe {
// Safety: all bitpatterns are valid for u32
let rng_array: [u32; 100] = MaybeUninit::uninit().assume_init();
// Safety: The `random_number` is in bounds
*rng_array.get_unchecked(random_number as usize)
}
} else {
// chosen by a fair dice roll
4
};
dbg!(very_random_number);
}
Solution
warning: the type `u8` does not permit being left uninitialized
--> examples/unsafe_2.rs:5:38
|
5 | let random_number: u8 = unsafe { MaybeUninit::uninit().assume_init() };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| this code causes undefined behavior when executed
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
|
= note: integers must be initialized
= note: `#[warn(invalid_value)]` on by default
warning: the type `[u32; 100]` does not permit being left uninitialized
--> examples/unsafe_2.rs:10:41
|
10 | let rng_array: [u32; 100] = MaybeUninit::uninit().assume_init();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| this code causes undefined behavior when executed
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
|
= note: integers must be initialized
error: Undefined Behavior: reading memory at alloc133[0x0..0x1], but memory is uninitialized at [0x0..0x1], and this operation requires initialized memory
--> examples/unsafe_2.rs:5:38
|
5 | let random_number: u8 = unsafe { MaybeUninit::uninit().assume_init() };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: inside `main` at examples/unsafe_2.rs:5:38: 5:73
Uninitialized memory occurred at alloc133[0x0..0x1], in this allocation:
alloc133 (stack variable, size: 1, align: 1) {
__ │ ░
}
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
error: aborting due to 1 previous error; 2 warnings emitted
Even though all initialized bitpatterns are valid for integer types, creating an integer value from uninitialized memory is still undefined behavior. More details can be found in the MaybeUninit documentation.
Careful readers may also have noticed that there is an index out of bounds error from checking random_number <= 100 instead of random_number < 100. While this is logically incorrect, it does not result in any UB as the previous line when creating random_number is UB and thus all future lines are not executed.