@@ -50,6 +50,86 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a + 'mir>: crate::MiriEvalContextExt<'
50
50
Ok ( Some ( this. load_mir ( instance. def ) ?) )
51
51
}
52
52
53
+ fn malloc (
54
+ & mut self ,
55
+ size : u64 ,
56
+ zero_init : bool ,
57
+ ) -> Scalar < Tag > {
58
+ let this = self . eval_context_mut ( ) ;
59
+ let tcx = & { this. tcx . tcx } ;
60
+ if size == 0 {
61
+ Scalar :: from_int ( 0 , this. pointer_size ( ) )
62
+ } else {
63
+ let align = this. tcx . data_layout . pointer_align . abi ;
64
+ let ptr = this. memory_mut ( ) . allocate ( Size :: from_bytes ( size) , align, MiriMemoryKind :: C . into ( ) ) ;
65
+ if zero_init {
66
+ // We just allocated this, the access cannot fail
67
+ this. memory_mut ( )
68
+ . get_mut ( ptr. alloc_id ) . unwrap ( )
69
+ . write_repeat ( tcx, ptr, 0 , Size :: from_bytes ( size) ) . unwrap ( ) ;
70
+ }
71
+ Scalar :: Ptr ( ptr)
72
+ }
73
+ }
74
+
75
+ fn free (
76
+ & mut self ,
77
+ ptr : Scalar < Tag > ,
78
+ ) -> EvalResult < ' tcx > {
79
+ let this = self . eval_context_mut ( ) ;
80
+ if !ptr. is_null_ptr ( this) {
81
+ this. memory_mut ( ) . deallocate (
82
+ ptr. to_ptr ( ) ?,
83
+ None ,
84
+ MiriMemoryKind :: C . into ( ) ,
85
+ ) ?;
86
+ }
87
+ Ok ( ( ) )
88
+ }
89
+
90
+ fn realloc (
91
+ & mut self ,
92
+ old_ptr : Scalar < Tag > ,
93
+ new_size : u64 ,
94
+ ) -> EvalResult < ' tcx , Scalar < Tag > > {
95
+ let this = self . eval_context_mut ( ) ;
96
+ let align = this. tcx . data_layout . pointer_align . abi ;
97
+ if old_ptr. is_null_ptr ( this) {
98
+ if new_size == 0 {
99
+ Ok ( Scalar :: from_int ( 0 , this. pointer_size ( ) ) )
100
+ } else {
101
+ let new_ptr = this. memory_mut ( ) . allocate (
102
+ Size :: from_bytes ( new_size) ,
103
+ align,
104
+ MiriMemoryKind :: C . into ( )
105
+ ) ;
106
+ Ok ( Scalar :: Ptr ( new_ptr) )
107
+ }
108
+ } else {
109
+ let old_ptr = old_ptr. to_ptr ( ) ?;
110
+ let memory = this. memory_mut ( ) ;
111
+ let old_size = Size :: from_bytes ( memory. get ( old_ptr. alloc_id ) ?. bytes . len ( ) as u64 ) ;
112
+ if new_size == 0 {
113
+ memory. deallocate (
114
+ old_ptr,
115
+ Some ( ( old_size, align) ) ,
116
+ MiriMemoryKind :: C . into ( ) ,
117
+ ) ?;
118
+ Ok ( Scalar :: from_int ( 0 , this. pointer_size ( ) ) )
119
+ } else {
120
+ let new_ptr = memory. reallocate (
121
+ old_ptr,
122
+ old_size,
123
+ align,
124
+ Size :: from_bytes ( new_size) ,
125
+ align,
126
+ MiriMemoryKind :: C . into ( ) ,
127
+ ) ?;
128
+ Ok ( Scalar :: Ptr ( new_ptr) )
129
+ }
130
+ }
131
+ }
132
+
53
133
/// Emulates calling a foreign item, failing if the item is not supported.
54
134
/// This function will handle `goto_block` if needed.
55
135
fn emulate_foreign_item (
@@ -95,28 +175,15 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a + 'mir>: crate::MiriEvalContextExt<'
95
175
match link_name {
96
176
"malloc" => {
97
177
let size = this. read_scalar ( args[ 0 ] ) ?. to_usize ( this) ?;
98
- if size == 0 {
99
- this. write_null ( dest) ?;
100
- } else {
101
- let align = this. tcx . data_layout . pointer_align . abi ;
102
- let ptr = this. memory_mut ( ) . allocate ( Size :: from_bytes ( size) , align, MiriMemoryKind :: C . into ( ) ) ;
103
- this. write_scalar ( Scalar :: Ptr ( ptr) , dest) ?;
104
- }
178
+ let res = this. malloc ( size, /*zero_init:*/ false ) ;
179
+ this. write_scalar ( res, dest) ?;
105
180
}
106
181
"calloc" => {
107
182
let items = this. read_scalar ( args[ 0 ] ) ?. to_usize ( this) ?;
108
183
let len = this. read_scalar ( args[ 1 ] ) ?. to_usize ( this) ?;
109
- let bytes = items. checked_mul ( len) . ok_or_else ( || InterpError :: Overflow ( mir:: BinOp :: Mul ) ) ?;
110
-
111
- if bytes == 0 {
112
- this. write_null ( dest) ?;
113
- } else {
114
- let size = Size :: from_bytes ( bytes) ;
115
- let align = this. tcx . data_layout . pointer_align . abi ;
116
- let ptr = this. memory_mut ( ) . allocate ( size, align, MiriMemoryKind :: C . into ( ) ) ;
117
- this. memory_mut ( ) . get_mut ( ptr. alloc_id ) ?. write_repeat ( tcx, ptr, 0 , size) ?;
118
- this. write_scalar ( Scalar :: Ptr ( ptr) , dest) ?;
119
- }
184
+ let size = items. checked_mul ( len) . ok_or_else ( || InterpError :: Overflow ( mir:: BinOp :: Mul ) ) ?;
185
+ let res = this. malloc ( size, /*zero_init:*/ true ) ;
186
+ this. write_scalar ( res, dest) ?;
120
187
}
121
188
"posix_memalign" => {
122
189
let ret = this. deref_operand ( args[ 0 ] ) ?;
@@ -144,55 +211,15 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a + 'mir>: crate::MiriEvalContextExt<'
144
211
}
145
212
this. write_null ( dest) ?;
146
213
}
147
-
148
214
"free" => {
149
215
let ptr = this. read_scalar ( args[ 0 ] ) ?. not_undef ( ) ?;
150
- if !ptr. is_null_ptr ( this) {
151
- this. memory_mut ( ) . deallocate (
152
- ptr. to_ptr ( ) ?,
153
- None ,
154
- MiriMemoryKind :: C . into ( ) ,
155
- ) ?;
156
- }
216
+ this. free ( ptr) ?;
157
217
}
158
218
"realloc" => {
159
219
let old_ptr = this. read_scalar ( args[ 0 ] ) ?. not_undef ( ) ?;
160
220
let new_size = this. read_scalar ( args[ 1 ] ) ?. to_usize ( this) ?;
161
- let align = this. tcx . data_layout . pointer_align . abi ;
162
- if old_ptr. is_null_ptr ( this) {
163
- if new_size == 0 {
164
- this. write_null ( dest) ?;
165
- } else {
166
- let new_ptr = this. memory_mut ( ) . allocate (
167
- Size :: from_bytes ( new_size) ,
168
- align,
169
- MiriMemoryKind :: C . into ( )
170
- ) ;
171
- this. write_scalar ( Scalar :: Ptr ( new_ptr) , dest) ?;
172
- }
173
- } else {
174
- let old_ptr = old_ptr. to_ptr ( ) ?;
175
- let memory = this. memory_mut ( ) ;
176
- let old_size = Size :: from_bytes ( memory. get ( old_ptr. alloc_id ) ?. bytes . len ( ) as u64 ) ;
177
- if new_size == 0 {
178
- memory. deallocate (
179
- old_ptr,
180
- Some ( ( old_size, align) ) ,
181
- MiriMemoryKind :: C . into ( ) ,
182
- ) ?;
183
- this. write_null ( dest) ?;
184
- } else {
185
- let new_ptr = memory. reallocate (
186
- old_ptr,
187
- old_size,
188
- align,
189
- Size :: from_bytes ( new_size) ,
190
- align,
191
- MiriMemoryKind :: C . into ( ) ,
192
- ) ?;
193
- this. write_scalar ( Scalar :: Ptr ( new_ptr) , dest) ?;
194
- }
195
- }
221
+ let res = this. realloc ( old_ptr, new_size) ?;
222
+ this. write_scalar ( res, dest) ?;
196
223
}
197
224
198
225
"__rust_alloc" => {
@@ -279,19 +306,14 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a + 'mir>: crate::MiriEvalContextExt<'
279
306
// is called if a `HashMap` is created the regular way (e.g. HashMap<K, V>).
280
307
match this. read_scalar ( args[ 0 ] ) ?. to_usize ( this) ? {
281
308
id if id == sys_getrandom => {
282
- let ptr = this. read_scalar ( args[ 1 ] ) ?. to_ptr ( ) ?;
309
+ let ptr = this. read_scalar ( args[ 1 ] ) ?. not_undef ( ) ?;
283
310
let len = this. read_scalar ( args[ 2 ] ) ?. to_usize ( this) ?;
284
311
285
312
// The only supported flags are GRND_RANDOM and GRND_NONBLOCK,
286
313
// neither of which have any effect on our current PRNG
287
314
let _flags = this. read_scalar ( args[ 3 ] ) ?. to_i32 ( ) ?;
288
315
289
- if len > 0 {
290
- let data = gen_random ( this, len as usize ) ?;
291
- this. memory_mut ( ) . get_mut ( ptr. alloc_id ) ?
292
- . write_bytes ( tcx, ptr, & data) ?;
293
- }
294
-
316
+ gen_random ( this, len as usize , ptr) ?;
295
317
this. write_scalar ( Scalar :: from_uint ( len, dest. layout . size ) , dest) ?;
296
318
}
297
319
id => {
@@ -693,8 +715,43 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a + 'mir>: crate::MiriEvalContextExt<'
693
715
"_NSGetArgv" => {
694
716
this. write_scalar ( Scalar :: Ptr ( this. machine . argv . unwrap ( ) ) , dest) ?;
695
717
} ,
718
+ "SecRandomCopyBytes" => {
719
+ let len = this. read_scalar ( args[ 1 ] ) ?. to_usize ( this) ?;
720
+ let ptr = this. read_scalar ( args[ 2 ] ) ?. not_undef ( ) ?;
721
+ gen_random ( this, len as usize , ptr) ?;
722
+ this. write_null ( dest) ?;
723
+ }
696
724
697
725
// Windows API stubs.
726
+ // HANDLE = isize
727
+ // DWORD = ULONG = u32
728
+ "GetProcessHeap" => {
729
+ // Just fake a HANDLE
730
+ this. write_scalar ( Scalar :: from_int ( 1 , this. pointer_size ( ) ) , dest) ?;
731
+ }
732
+ "HeapAlloc" => {
733
+ let _handle = this. read_scalar ( args[ 0 ] ) ?. to_isize ( this) ?;
734
+ let flags = this. read_scalar ( args[ 1 ] ) ?. to_u32 ( ) ?;
735
+ let size = this. read_scalar ( args[ 2 ] ) ?. to_usize ( this) ?;
736
+ let zero_init = ( flags & 0x00000008 ) != 0 ; // HEAP_ZERO_MEMORY
737
+ let res = this. malloc ( size, zero_init) ;
738
+ this. write_scalar ( res, dest) ?;
739
+ }
740
+ "HeapFree" => {
741
+ let _handle = this. read_scalar ( args[ 0 ] ) ?. to_isize ( this) ?;
742
+ let _flags = this. read_scalar ( args[ 1 ] ) ?. to_u32 ( ) ?;
743
+ let ptr = this. read_scalar ( args[ 2 ] ) ?. not_undef ( ) ?;
744
+ this. free ( ptr) ?;
745
+ }
746
+ "HeapReAlloc" => {
747
+ let _handle = this. read_scalar ( args[ 0 ] ) ?. to_isize ( this) ?;
748
+ let _flags = this. read_scalar ( args[ 1 ] ) ?. to_u32 ( ) ?;
749
+ let ptr = this. read_scalar ( args[ 2 ] ) ?. not_undef ( ) ?;
750
+ let size = this. read_scalar ( args[ 3 ] ) ?. to_usize ( this) ?;
751
+ let res = this. realloc ( ptr, size) ?;
752
+ this. write_scalar ( res, dest) ?;
753
+ }
754
+
698
755
"SetLastError" => {
699
756
let err = this. read_scalar ( args[ 0 ] ) ?. to_u32 ( ) ?;
700
757
this. machine . last_error = err;
@@ -818,15 +875,9 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a + 'mir>: crate::MiriEvalContextExt<'
818
875
}
819
876
// The actual name of 'RtlGenRandom'
820
877
"SystemFunction036" => {
821
- let ptr = this. read_scalar ( args[ 0 ] ) ?. to_ptr ( ) ?;
878
+ let ptr = this. read_scalar ( args[ 0 ] ) ?. not_undef ( ) ?;
822
879
let len = this. read_scalar ( args[ 1 ] ) ?. to_u32 ( ) ?;
823
-
824
- if len > 0 {
825
- let data = gen_random ( this, len as usize ) ?;
826
- this. memory_mut ( ) . get_mut ( ptr. alloc_id ) ?
827
- . write_bytes ( tcx, ptr, & data) ?;
828
- }
829
-
880
+ gen_random ( this, len as usize , ptr) ?;
830
881
this. write_scalar ( Scalar :: from_bool ( true ) , dest) ?;
831
882
}
832
883
@@ -867,21 +918,30 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a + 'mir>: crate::MiriEvalContextExt<'
867
918
fn gen_random < ' a , ' mir , ' tcx > (
868
919
this : & mut MiriEvalContext < ' a , ' mir , ' tcx > ,
869
920
len : usize ,
870
- ) -> Result < Vec < u8 > , EvalError < ' tcx > > {
921
+ dest : Scalar < Tag > ,
922
+ ) -> EvalResult < ' tcx > {
923
+ if len == 0 {
924
+ // Nothing to do
925
+ return Ok ( ( ) ) ;
926
+ }
927
+ let ptr = dest. to_ptr ( ) ?;
871
928
872
- match & mut this. machine . rng {
929
+ let data = match & mut this. machine . rng {
873
930
Some ( rng) => {
874
931
let mut data = vec ! [ 0 ; len] ;
875
932
rng. fill_bytes ( & mut data) ;
876
- Ok ( data)
933
+ data
877
934
}
878
935
None => {
879
- err ! ( Unimplemented (
936
+ return err ! ( Unimplemented (
880
937
"miri does not support gathering system entropy in deterministic mode!
881
938
Use '-Zmiri-seed=<seed>' to enable random number generation.
882
939
WARNING: Miri does *not* generate cryptographically secure entropy -
883
940
do not use Miri to run any program that needs secure random number generation" . to_owned( ) ,
884
- ) )
941
+ ) ) ;
885
942
}
886
- }
943
+ } ;
944
+ let tcx = & { this. tcx . tcx } ;
945
+ this. memory_mut ( ) . get_mut ( ptr. alloc_id ) ?
946
+ . write_bytes ( tcx, ptr, & data)
887
947
}
0 commit comments