@@ -50,11 +50,12 @@ pub fn create_ecx<'a, 'mir: 'a, 'tcx: 'mir>(
5050 tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
5151 main_id : DefId ,
5252 start_wrapper : Option < DefId > ,
53+ validate : bool ,
5354) -> EvalResult < ' tcx , EvalContext < ' a , ' mir , ' tcx , Evaluator < ' tcx > > > {
5455 let mut ecx = EvalContext :: new (
5556 tcx. at ( syntax:: source_map:: DUMMY_SP ) ,
5657 ty:: ParamEnv :: reveal_all ( ) ,
57- Default :: default ( ) ,
58+ Evaluator :: new ( validate ) ,
5859 Default :: default ( ) ,
5960 ) ;
6061
@@ -67,7 +68,6 @@ pub fn create_ecx<'a, 'mir: 'a, 'tcx: 'mir>(
6768 . to_owned( ) ,
6869 ) ) ;
6970 }
70- let ptr_size = ecx. memory . pointer_size ( ) ;
7171
7272 if let Some ( start_id) = start_wrapper {
7373 let main_ret_ty = ecx. tcx . fn_sig ( main_id) . output ( ) ;
@@ -89,16 +89,15 @@ pub fn create_ecx<'a, 'mir: 'a, 'tcx: 'mir>(
8989 }
9090
9191 // Return value (in static memory so that it does not count as leak)
92- let size = ecx. tcx . data_layout . pointer_size ;
93- let align = ecx. tcx . data_layout . pointer_align ;
94- let ret_ptr = ecx. memory_mut ( ) . allocate ( size, align, MiriMemoryKind :: MutStatic . into ( ) ) ?;
92+ let ret = ecx. layout_of ( start_mir. return_ty ( ) ) ?;
93+ let ret_ptr = ecx. allocate ( ret, MiriMemoryKind :: MutStatic . into ( ) ) ?;
9594
9695 // Push our stack frame
9796 ecx. push_stack_frame (
9897 start_instance,
9998 start_mir. span ,
10099 start_mir,
101- Place :: from_ptr ( ret_ptr, align ) ,
100+ Some ( ret_ptr. into ( ) ) ,
102101 StackPopCleanup :: None { cleanup : true } ,
103102 ) ?;
104103
@@ -126,11 +125,12 @@ pub fn create_ecx<'a, 'mir: 'a, 'tcx: 'mir>(
126125
127126 assert ! ( args. next( ) . is_none( ) , "start lang item has more arguments than expected" ) ;
128127 } else {
128+ let ret_place = MPlaceTy :: dangling ( ecx. layout_of ( tcx. mk_unit ( ) ) ?, & ecx) . into ( ) ;
129129 ecx. push_stack_frame (
130130 main_instance,
131131 main_mir. span ,
132132 main_mir,
133- Place :: from_scalar_ptr ( Scalar :: from_int ( 1 , ptr_size ) . into ( ) , ty :: layout :: Align :: from_bytes ( 1 , 1 ) . unwrap ( ) ) ,
133+ Some ( ret_place ) ,
134134 StackPopCleanup :: None { cleanup : true } ,
135135 ) ?;
136136
@@ -146,8 +146,9 @@ pub fn eval_main<'a, 'tcx: 'a>(
146146 tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
147147 main_id : DefId ,
148148 start_wrapper : Option < DefId > ,
149+ validate : bool ,
149150) {
150- let mut ecx = create_ecx ( tcx, main_id, start_wrapper) . expect ( "Couldn't create ecx" ) ;
151+ let mut ecx = create_ecx ( tcx, main_id, start_wrapper, validate ) . expect ( "Couldn't create ecx" ) ;
151152
152153 let res: EvalResult = ( || {
153154 ecx. run ( ) ?;
@@ -222,14 +223,27 @@ impl Into<MemoryKind<MiriMemoryKind>> for MiriMemoryKind {
222223}
223224
224225
225- #[ derive( Clone , Default , PartialEq , Eq ) ]
226+ #[ derive( Clone , PartialEq , Eq ) ]
226227pub struct Evaluator < ' tcx > {
227228 /// Environment variables set by `setenv`
228229 /// Miri does not expose env vars from the host to the emulated program
229230 pub ( crate ) env_vars : HashMap < Vec < u8 > , Pointer > ,
230231
231232 /// TLS state
232233 pub ( crate ) tls : TlsData < ' tcx > ,
234+
235+ /// Whether to enforce the validity invariant
236+ pub ( crate ) validate : bool ,
237+ }
238+
239+ impl < ' tcx > Evaluator < ' tcx > {
240+ fn new ( validate : bool ) -> Self {
241+ Evaluator {
242+ env_vars : HashMap :: default ( ) ,
243+ tls : TlsData :: default ( ) ,
244+ validate,
245+ }
246+ }
233247}
234248
235249impl < ' a , ' mir , ' tcx > Machine < ' a , ' mir , ' tcx > for Evaluator < ' tcx > {
@@ -240,7 +254,29 @@ impl<'a, 'mir, 'tcx> Machine<'a, 'mir, 'tcx> for Evaluator<'tcx> {
240254 type MemoryMap = MonoHashMap < AllocId , ( MemoryKind < MiriMemoryKind > , Allocation < ( ) > ) > ;
241255
242256 const STATIC_KIND : Option < MiriMemoryKind > = Some ( MiriMemoryKind :: MutStatic ) ;
243- const ENFORCE_VALIDITY : bool = false ; // this is still WIP
257+
258+ fn enforce_validity ( ecx : & EvalContext < ' a , ' mir , ' tcx , Self > ) -> bool {
259+ if !ecx. machine . validate {
260+ return false ;
261+ }
262+
263+ // Some functions are whitelisted until we figure out how to fix them.
264+ // We walk up the stack a few frames to also cover their callees.
265+ const WHITELIST : & [ & str ] = & [
266+ // Uses mem::uninitialized
267+ "std::ptr::read" ,
268+ "std::sys::windows::mutex::Mutex::" ,
269+ ] ;
270+ for frame in ecx. stack ( ) . iter ( )
271+ . rev ( ) . take ( 3 )
272+ {
273+ let name = frame. instance . to_string ( ) ;
274+ if WHITELIST . iter ( ) . any ( |white| name. starts_with ( white) ) {
275+ return false ;
276+ }
277+ }
278+ true
279+ }
244280
245281 /// Returns Ok() when the function was handled, fail otherwise
246282 fn find_fn (
@@ -286,7 +322,7 @@ impl<'a, 'mir, 'tcx> Machine<'a, 'mir, 'tcx> for Evaluator<'tcx> {
286322 malloc,
287323 malloc_mir. span ,
288324 malloc_mir,
289- * dest,
325+ Some ( dest) ,
290326 // Don't do anything when we are done. The statement() function will increment
291327 // the old stack frame's stmt counter to the next statement, which means that when
292328 // exchange_malloc returns, we go on evaluating exactly where we want to be.
0 commit comments