|
extern "C" { |
|
fn sys_read_entropy(buffer: *mut u8, length: usize, flags: u32) -> isize; |
|
} |
|
|
|
while !dest.is_empty() { |
|
let res = unsafe { sys_read_entropy(dest.as_mut_ptr() as *mut u8, dest.len(), 0) }; |
|
if res < 0 { |
|
// SAFETY: all Hermit error codes use i32 under the hood: |
|
// https://github.com/hermitcore/libhermit-rs/blob/master/src/errno.rs |
|
let code = unsafe { NonZeroU32::new_unchecked((-res) as u32) }; |
|
return Err(code.into()); |
|
} |
- If
res == -sizie::MIN then (-res) will overflow. To fix, use checked_neg().
- if
res < (i32::MIN as isize) then (-res) as u32 is a truncating, i.e. lossy conversion. To fix: avoid using as for integer conversions and instead use TryInto for this conversion.
- if
(-res) % 0x1_0000_0000 == 0 then (-res) as u32 is zero and then NonZeroU32::new_unchecked((-res) as u32) is undefined behavior. To fix, use the safe NonZerou32::new() instead.
Maybe somewhere hermit guarantees errors codes will never be this large but better to avoid the issue completely.
Something like:
let code = res.checked_neg().map(u32::try_from).map(NonZeroU32::new).unwrap_or(something);
There would be no undefined behavior in the new version.
getrandom/src/hermit.rs
Lines 4 to 7 in 35808a4
getrandom/src/hermit.rs
Lines 9 to 16 in 35808a4
res == -sizie::MINthen(-res)will overflow. To fix, usechecked_neg().res < (i32::MIN as isize)then(-res) as u32is a truncating, i.e. lossy conversion. To fix: avoid usingasfor integer conversions and instead useTryIntofor this conversion.(-res) % 0x1_0000_0000 == 0then(-res) as u32is zero and thenNonZeroU32::new_unchecked((-res) as u32)is undefined behavior. To fix, use the safeNonZerou32::new()instead.Maybe somewhere hermit guarantees errors codes will never be this large but better to avoid the issue completely.
Something like:
There would be no undefined behavior in the new version.