@@ -982,29 +982,46 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
982
982
Ok ( ( true , string_length) )
983
983
}
984
984
985
- /// Read a sequence of u16 until the first null terminator.
986
- fn read_wide_str ( & self , mut ptr : Pointer < Option < Provenance > > ) -> InterpResult < ' tcx , Vec < u16 > > {
985
+ /// Helper function to read a sequence of unsigned integers of the given size and alignment
986
+ /// until the first null terminator.
987
+ fn read_c_str_with_char_size < T > (
988
+ & self ,
989
+ mut ptr : Pointer < Option < Provenance > > ,
990
+ size : Size ,
991
+ align : Align ,
992
+ ) -> InterpResult < ' tcx , Vec < T > >
993
+ where
994
+ T : TryFrom < u128 > ,
995
+ <T as TryFrom < u128 > >:: Error : std:: fmt:: Debug ,
996
+ {
997
+ assert_ne ! ( size, Size :: ZERO ) ;
998
+
987
999
let this = self . eval_context_ref ( ) ;
988
- let size2 = Size :: from_bytes ( 2 ) ;
989
- this. check_ptr_align ( ptr, Align :: from_bytes ( 2 ) . unwrap ( ) ) ?;
1000
+
1001
+ this. check_ptr_align ( ptr, align ) ?;
990
1002
991
1003
let mut wchars = Vec :: new ( ) ;
992
1004
loop {
993
1005
// FIXME: We are re-getting the allocation each time around the loop.
994
1006
// Would be nice if we could somehow "extend" an existing AllocRange.
995
- let alloc = this. get_ptr_alloc ( ptr, size2 ) ?. unwrap ( ) ; // not a ZST, so we will get a result
996
- let wchar = alloc. read_integer ( alloc_range ( Size :: ZERO , size2 ) ) ?. to_u16 ( ) ?;
997
- if wchar == 0 {
1007
+ let alloc = this. get_ptr_alloc ( ptr, size ) ?. unwrap ( ) ; // not a ZST, so we will get a result
1008
+ let wchar_int = alloc. read_integer ( alloc_range ( Size :: ZERO , size ) ) ?. to_bits ( size ) ?;
1009
+ if wchar_int == 0 {
998
1010
break ;
999
1011
} else {
1000
- wchars. push ( wchar ) ;
1001
- ptr = ptr. offset ( size2 , this) ?;
1012
+ wchars. push ( wchar_int . try_into ( ) . unwrap ( ) ) ;
1013
+ ptr = ptr. offset ( size , this) ?;
1002
1014
}
1003
1015
}
1004
1016
1005
1017
Ok ( wchars)
1006
1018
}
1007
1019
1020
+ /// Read a sequence of u16 until the first null terminator.
1021
+ fn read_wide_str ( & self , ptr : Pointer < Option < Provenance > > ) -> InterpResult < ' tcx , Vec < u16 > > {
1022
+ self . read_c_str_with_char_size ( ptr, Size :: from_bytes ( 2 ) , Align :: from_bytes ( 2 ) . unwrap ( ) )
1023
+ }
1024
+
1008
1025
/// Helper function to write a sequence of u16 with an added 0x0000-terminator, which is what
1009
1026
/// the Windows APIs usually handle. This function returns `Ok((false, length))` without trying
1010
1027
/// to write if `size` is not large enough to fit the contents of `os_string` plus a null
@@ -1037,6 +1054,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
1037
1054
Ok ( ( true , string_length) )
1038
1055
}
1039
1056
1057
+ /// Read a sequence of wchar_t until the first null terminator.
1058
+ /// Always returns a `Vec<u32>` no matter the size of `wchar_t`.
1059
+ fn read_wchar_t_str ( & self , ptr : Pointer < Option < Provenance > > ) -> InterpResult < ' tcx , Vec < u32 > > {
1060
+ let this = self . eval_context_ref ( ) ;
1061
+ let wchar_t = this. libc_ty_layout ( "wchar_t" ) ;
1062
+ self . read_c_str_with_char_size ( ptr, wchar_t. size , wchar_t. align . abi )
1063
+ }
1064
+
1040
1065
/// Check that the ABI is what we expect.
1041
1066
fn check_abi < ' a > ( & self , abi : Abi , exp_abi : Abi ) -> InterpResult < ' a , ( ) > {
1042
1067
if abi != exp_abi {
0 commit comments