11use crate :: Error ;
2- use core:: { cmp:: min, mem:: MaybeUninit , num:: NonZeroU32 } ;
2+ use core:: { mem:: MaybeUninit , num:: NonZeroU32 } ;
3+
4+ /// Minimum return value which we should get from syscalls in practice,
5+ /// because Hermit uses positive `i32`s for error codes:
6+ /// https://github.com/hermitcore/libhermit-rs/blob/main/src/errno.rs
7+ const MIN_RET_CODE : isize = -( i32:: MAX as isize ) ;
38
49extern "C" {
510 fn sys_read_entropy ( buffer : * mut u8 , length : usize , flags : u32 ) -> isize ;
@@ -8,14 +13,16 @@ extern "C" {
813pub fn getrandom_inner ( mut dest : & mut [ MaybeUninit < u8 > ] ) -> Result < ( ) , Error > {
914 while !dest. is_empty ( ) {
1015 let res = unsafe { sys_read_entropy ( dest. as_mut_ptr ( ) as * mut u8 , dest. len ( ) , 0 ) } ;
11- if res < 0 {
12- // SAFETY: all Hermit error codes use i32 under the hood:
13- // https://github.com/hermitcore/libhermit-rs/blob/master/src/errno.rs
14- let code = unsafe { NonZeroU32 :: new_unchecked ( ( -res) as u32 ) } ;
15- return Err ( code. into ( ) ) ;
16+ // Positive `isize`s can be safely casted to `usize`
17+ if res > 0 && ( res as usize ) <= dest. len ( ) {
18+ dest = & mut dest[ res as usize ..] ;
19+ } else {
20+ let err = match res {
21+ MIN_RET_CODE ..=-1 => NonZeroU32 :: new ( -res as u32 ) . unwrap ( ) . into ( ) ,
22+ _ => Error :: UNEXPECTED ,
23+ } ;
24+ return Err ( err) ;
1625 }
17- let len = min ( res as usize , dest. len ( ) ) ;
18- dest = & mut dest[ len..] ;
1926 }
2027 Ok ( ( ) )
2128}
0 commit comments