@@ -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 (
@@ -87,28 +167,15 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a + 'mir>: crate::MiriEvalContextExt<'
87
167
match link_name {
88
168
"malloc" => {
89
169
let size = this. read_scalar ( args[ 0 ] ) ?. to_usize ( this) ?;
90
- if size == 0 {
91
- this. write_null ( dest) ?;
92
- } else {
93
- let align = this. tcx . data_layout . pointer_align . abi ;
94
- let ptr = this. memory_mut ( ) . allocate ( Size :: from_bytes ( size) , align, MiriMemoryKind :: C . into ( ) ) ;
95
- this. write_scalar ( Scalar :: Ptr ( ptr) , dest) ?;
96
- }
170
+ let res = this. malloc ( size, /*zero_init:*/ false ) ;
171
+ this. write_scalar ( res, dest) ?;
97
172
}
98
173
"calloc" => {
99
174
let items = this. read_scalar ( args[ 0 ] ) ?. to_usize ( this) ?;
100
175
let len = this. read_scalar ( args[ 1 ] ) ?. to_usize ( this) ?;
101
- let bytes = items. checked_mul ( len) . ok_or_else ( || InterpError :: Overflow ( mir:: BinOp :: Mul ) ) ?;
102
-
103
- if bytes == 0 {
104
- this. write_null ( dest) ?;
105
- } else {
106
- let size = Size :: from_bytes ( bytes) ;
107
- let align = this. tcx . data_layout . pointer_align . abi ;
108
- let ptr = this. memory_mut ( ) . allocate ( size, align, MiriMemoryKind :: C . into ( ) ) ;
109
- this. memory_mut ( ) . get_mut ( ptr. alloc_id ) ?. write_repeat ( tcx, ptr, 0 , size) ?;
110
- this. write_scalar ( Scalar :: Ptr ( ptr) , dest) ?;
111
- }
176
+ let size = items. checked_mul ( len) . ok_or_else ( || InterpError :: Overflow ( mir:: BinOp :: Mul ) ) ?;
177
+ let res = this. malloc ( size, /*zero_init:*/ true ) ;
178
+ this. write_scalar ( res, dest) ?;
112
179
}
113
180
"posix_memalign" => {
114
181
let ret = this. deref_operand ( args[ 0 ] ) ?;
@@ -136,55 +203,15 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a + 'mir>: crate::MiriEvalContextExt<'
136
203
}
137
204
this. write_null ( dest) ?;
138
205
}
139
-
140
206
"free" => {
141
207
let ptr = this. read_scalar ( args[ 0 ] ) ?. not_undef ( ) ?;
142
- if !ptr. is_null_ptr ( this) {
143
- this. memory_mut ( ) . deallocate (
144
- ptr. to_ptr ( ) ?,
145
- None ,
146
- MiriMemoryKind :: C . into ( ) ,
147
- ) ?;
148
- }
208
+ this. free ( ptr) ?;
149
209
}
150
210
"realloc" => {
151
211
let old_ptr = this. read_scalar ( args[ 0 ] ) ?. not_undef ( ) ?;
152
212
let new_size = this. read_scalar ( args[ 1 ] ) ?. to_usize ( this) ?;
153
- let align = this. tcx . data_layout . pointer_align . abi ;
154
- if old_ptr. is_null_ptr ( this) {
155
- if new_size == 0 {
156
- this. write_null ( dest) ?;
157
- } else {
158
- let new_ptr = this. memory_mut ( ) . allocate (
159
- Size :: from_bytes ( new_size) ,
160
- align,
161
- MiriMemoryKind :: C . into ( )
162
- ) ;
163
- this. write_scalar ( Scalar :: Ptr ( new_ptr) , dest) ?;
164
- }
165
- } else {
166
- let old_ptr = old_ptr. to_ptr ( ) ?;
167
- let memory = this. memory_mut ( ) ;
168
- let old_size = Size :: from_bytes ( memory. get ( old_ptr. alloc_id ) ?. bytes . len ( ) as u64 ) ;
169
- if new_size == 0 {
170
- memory. deallocate (
171
- old_ptr,
172
- Some ( ( old_size, align) ) ,
173
- MiriMemoryKind :: C . into ( ) ,
174
- ) ?;
175
- this. write_null ( dest) ?;
176
- } else {
177
- let new_ptr = memory. reallocate (
178
- old_ptr,
179
- old_size,
180
- align,
181
- Size :: from_bytes ( new_size) ,
182
- align,
183
- MiriMemoryKind :: C . into ( ) ,
184
- ) ?;
185
- this. write_scalar ( Scalar :: Ptr ( new_ptr) , dest) ?;
186
- }
187
- }
213
+ let res = this. realloc ( old_ptr, new_size) ?;
214
+ this. write_scalar ( res, dest) ?;
188
215
}
189
216
190
217
"__rust_alloc" => {
@@ -687,6 +714,35 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a + 'mir>: crate::MiriEvalContextExt<'
687
714
} ,
688
715
689
716
// Windows API stubs.
717
+ // HANDLE = isize
718
+ // DWORD = ULONG = u32
719
+ "GetProcessHeap" => {
720
+ // Just fake a HANDLE
721
+ this. write_scalar ( Scalar :: from_int ( 1 , this. pointer_size ( ) ) , dest) ?;
722
+ }
723
+ "HeapAlloc" => {
724
+ let _handle = this. read_scalar ( args[ 0 ] ) ?. to_isize ( this) ?;
725
+ let flags = this. read_scalar ( args[ 1 ] ) ?. to_u32 ( ) ?;
726
+ let size = this. read_scalar ( args[ 2 ] ) ?. to_usize ( this) ?;
727
+ let zero_init = ( flags & 0x00000008 ) != 0 ; // HEAP_ZERO_MEMORY
728
+ let res = this. malloc ( size, zero_init) ;
729
+ this. write_scalar ( res, dest) ?;
730
+ }
731
+ "HeapFree" => {
732
+ let _handle = this. read_scalar ( args[ 0 ] ) ?. to_isize ( this) ?;
733
+ let _flags = this. read_scalar ( args[ 1 ] ) ?. to_u32 ( ) ?;
734
+ let ptr = this. read_scalar ( args[ 2 ] ) ?. not_undef ( ) ?;
735
+ this. free ( ptr) ?;
736
+ }
737
+ "HeapReAlloc" => {
738
+ let _handle = this. read_scalar ( args[ 0 ] ) ?. to_isize ( this) ?;
739
+ let _flags = this. read_scalar ( args[ 1 ] ) ?. to_u32 ( ) ?;
740
+ let ptr = this. read_scalar ( args[ 2 ] ) ?. not_undef ( ) ?;
741
+ let size = this. read_scalar ( args[ 3 ] ) ?. to_usize ( this) ?;
742
+ let res = this. realloc ( ptr, size) ?;
743
+ this. write_scalar ( res, dest) ?;
744
+ }
745
+
690
746
"SetLastError" => {
691
747
let err = this. read_scalar ( args[ 0 ] ) ?. to_u32 ( ) ?;
692
748
this. machine . last_error = err;
0 commit comments