1
1
use 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 ) ;
3
8
4
9
extern "C" {
5
10
fn sys_read_entropy ( buffer : * mut u8 , length : usize , flags : u32 ) -> isize ;
@@ -8,14 +13,16 @@ extern "C" {
8
13
pub fn getrandom_inner ( mut dest : & mut [ MaybeUninit < u8 > ] ) -> Result < ( ) , Error > {
9
14
while !dest. is_empty ( ) {
10
15
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) ;
16
25
}
17
- let len = min ( res as usize , dest. len ( ) ) ;
18
- dest = & mut dest[ len..] ;
19
26
}
20
27
Ok ( ( ) )
21
28
}
0 commit comments