@@ -42,6 +42,9 @@ pub struct EvalContext<'a, 'tcx: 'a> {
4242
4343 /// The virtual call stack.
4444 stack : Vec < Frame < ' a , ' tcx > > ,
45+
46+ /// The maximum number of stack frames allowed
47+ stack_limit : usize ,
4548}
4649
4750/// A stack frame.
@@ -133,24 +136,25 @@ enum ConstantKind {
133136}
134137
135138impl < ' a , ' tcx > EvalContext < ' a , ' tcx > {
136- pub fn new ( tcx : TyCtxt < ' a , ' tcx , ' tcx > , mir_map : & ' a MirMap < ' tcx > ) -> Self {
139+ pub fn new ( tcx : TyCtxt < ' a , ' tcx , ' tcx > , mir_map : & ' a MirMap < ' tcx > , memory_size : usize , stack_limit : usize ) -> Self {
137140 EvalContext {
138141 tcx : tcx,
139142 mir_map : mir_map,
140143 mir_cache : RefCell :: new ( DefIdMap ( ) ) ,
141- memory : Memory :: new ( & tcx. data_layout ) ,
144+ memory : Memory :: new ( & tcx. data_layout , memory_size ) ,
142145 statics : HashMap :: new ( ) ,
143146 stack : Vec :: new ( ) ,
147+ stack_limit : stack_limit,
144148 }
145149 }
146150
147- pub fn alloc_ret_ptr ( & mut self , output_ty : ty:: FnOutput < ' tcx > , substs : & ' tcx Substs < ' tcx > ) -> Option < Pointer > {
151+ pub fn alloc_ret_ptr ( & mut self , output_ty : ty:: FnOutput < ' tcx > , substs : & ' tcx Substs < ' tcx > ) -> EvalResult < ' tcx , Option < Pointer > > {
148152 match output_ty {
149153 ty:: FnConverging ( ty) => {
150154 let size = self . type_size_with_substs ( ty, substs) ;
151- Some ( self . memory . allocate ( size) )
155+ self . memory . allocate ( size) . map ( Some )
152156 }
153- ty:: FnDiverging => None ,
157+ ty:: FnDiverging => Ok ( None ) ,
154158 }
155159 }
156160
@@ -172,19 +176,19 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
172176 use rustc_const_math:: { ConstInt , ConstIsize , ConstUsize , ConstFloat } ;
173177 macro_rules! i2p {
174178 ( $i: ident, $n: expr) => { {
175- let ptr = self . memory. allocate( $n) ;
179+ let ptr = self . memory. allocate( $n) ? ;
176180 self . memory. write_int( ptr, $i as i64 , $n) ?;
177181 Ok ( ptr)
178182 } }
179183 }
180184 match * const_val {
181185 Float ( ConstFloat :: F32 ( f) ) => {
182- let ptr = self . memory . allocate ( 4 ) ;
186+ let ptr = self . memory . allocate ( 4 ) ? ;
183187 self . memory . write_f32 ( ptr, f) ?;
184188 Ok ( ptr)
185189 } ,
186190 Float ( ConstFloat :: F64 ( f) ) => {
187- let ptr = self . memory . allocate ( 8 ) ;
191+ let ptr = self . memory . allocate ( 8 ) ? ;
188192 self . memory . write_f64 ( ptr, f) ?;
189193 Ok ( ptr)
190194 } ,
@@ -207,28 +211,28 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
207211 Integral ( ConstInt :: Usize ( ConstUsize :: Us64 ( i) ) ) => i2p ! ( i, 8 ) ,
208212 Str ( ref s) => {
209213 let psize = self . memory . pointer_size ( ) ;
210- let static_ptr = self . memory . allocate ( s. len ( ) ) ;
211- let ptr = self . memory . allocate ( psize * 2 ) ;
214+ let static_ptr = self . memory . allocate ( s. len ( ) ) ? ;
215+ let ptr = self . memory . allocate ( psize * 2 ) ? ;
212216 self . memory . write_bytes ( static_ptr, s. as_bytes ( ) ) ?;
213217 self . memory . write_ptr ( ptr, static_ptr) ?;
214218 self . memory . write_usize ( ptr. offset ( psize as isize ) , s. len ( ) as u64 ) ?;
215219 Ok ( ptr)
216220 }
217221 ByteStr ( ref bs) => {
218222 let psize = self . memory . pointer_size ( ) ;
219- let static_ptr = self . memory . allocate ( bs. len ( ) ) ;
220- let ptr = self . memory . allocate ( psize) ;
223+ let static_ptr = self . memory . allocate ( bs. len ( ) ) ? ;
224+ let ptr = self . memory . allocate ( psize) ? ;
221225 self . memory . write_bytes ( static_ptr, bs) ?;
222226 self . memory . write_ptr ( ptr, static_ptr) ?;
223227 Ok ( ptr)
224228 }
225229 Bool ( b) => {
226- let ptr = self . memory . allocate ( 1 ) ;
230+ let ptr = self . memory . allocate ( 1 ) ? ;
227231 self . memory . write_bool ( ptr, b) ?;
228232 Ok ( ptr)
229233 }
230234 Char ( c) => {
231- let ptr = self . memory . allocate ( 4 ) ;
235+ let ptr = self . memory . allocate ( 4 ) ? ;
232236 self . memory . write_uint ( ptr, c as u64 , 4 ) ?;
233237 Ok ( ptr)
234238 } ,
@@ -292,9 +296,14 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
292296 } )
293297 }
294298
295- pub fn push_stack_frame ( & mut self , def_id : DefId , span : codemap:: Span , mir : CachedMir < ' a , ' tcx > , substs : & ' tcx Substs < ' tcx > ,
296- return_ptr : Option < Pointer > )
297- {
299+ pub fn push_stack_frame (
300+ & mut self ,
301+ def_id : DefId ,
302+ span : codemap:: Span ,
303+ mir : CachedMir < ' a , ' tcx > ,
304+ substs : & ' tcx Substs < ' tcx > ,
305+ return_ptr : Option < Pointer > ,
306+ ) -> EvalResult < ' tcx , ( ) > {
298307 let arg_tys = mir. arg_decls . iter ( ) . map ( |a| a. ty ) ;
299308 let var_tys = mir. var_decls . iter ( ) . map ( |v| v. ty ) ;
300309 let temp_tys = mir. temp_decls . iter ( ) . map ( |t| t. ty ) ;
@@ -304,7 +313,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
304313
305314 :: log_settings:: settings ( ) . indentation += 1 ;
306315
307- let locals: Vec < Pointer > = arg_tys. chain ( var_tys) . chain ( temp_tys) . map ( |ty| {
316+ let locals: EvalResult < ' tcx , Vec < Pointer > > = arg_tys. chain ( var_tys) . chain ( temp_tys) . map ( |ty| {
308317 let size = self . type_size_with_substs ( ty, substs) ;
309318 self . memory . allocate ( size)
310319 } ) . collect ( ) ;
@@ -313,14 +322,19 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
313322 mir : mir. clone ( ) ,
314323 block : mir:: START_BLOCK ,
315324 return_ptr : return_ptr,
316- locals : locals,
325+ locals : locals? ,
317326 var_offset : num_args,
318327 temp_offset : num_args + num_vars,
319328 span : span,
320329 def_id : def_id,
321330 substs : substs,
322331 stmt : 0 ,
323332 } ) ;
333+ if self . stack . len ( ) > self . stack_limit {
334+ Err ( EvalError :: StackFrameLimitReached )
335+ } else {
336+ Ok ( ( ) )
337+ }
324338 }
325339
326340 fn pop_stack_frame ( & mut self ) {
@@ -548,7 +562,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
548562
549563 Box ( ty) => {
550564 let size = self . type_size ( ty) ;
551- let ptr = self . memory . allocate ( size) ;
565+ let ptr = self . memory . allocate ( size) ? ;
552566 self . memory . write_ptr ( dest, ptr) ?;
553567 }
554568
@@ -696,7 +710,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
696710 Item { def_id, substs } => {
697711 if let ty:: TyFnDef ( ..) = ty. sty {
698712 // function items are zero sized
699- Ok ( self . memory . allocate ( 0 ) )
713+ Ok ( self . memory . allocate ( 0 ) ? )
700714 } else {
701715 let cid = ConstantId {
702716 def_id : def_id,
@@ -935,37 +949,44 @@ pub fn eval_main<'a, 'tcx: 'a>(
935949 tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
936950 mir_map : & ' a MirMap < ' tcx > ,
937951 node_id : ast:: NodeId ,
952+ memory_size : usize ,
953+ step_limit : u64 ,
954+ stack_limit : usize ,
938955) {
939956 let mir = mir_map. map . get ( & node_id) . expect ( "no mir for main function" ) ;
940957 let def_id = tcx. map . local_def_id ( node_id) ;
941- let mut ecx = EvalContext :: new ( tcx, mir_map) ;
958+ let mut ecx = EvalContext :: new ( tcx, mir_map, memory_size , stack_limit ) ;
942959 let substs = tcx. mk_substs ( subst:: Substs :: empty ( ) ) ;
943- let return_ptr = ecx. alloc_ret_ptr ( mir. return_ty , substs) . expect ( "main function should not be diverging" ) ;
960+ let return_ptr = ecx. alloc_ret_ptr ( mir. return_ty , substs)
961+ . expect ( "should at least be able to allocate space for the main function's return value" )
962+ . expect ( "main function should not be diverging" ) ;
944963
945- ecx. push_stack_frame ( def_id, mir. span , CachedMir :: Ref ( mir) , substs, Some ( return_ptr) ) ;
964+ ecx. push_stack_frame ( def_id, mir. span , CachedMir :: Ref ( mir) , substs, Some ( return_ptr) )
965+ . expect ( "could not allocate first stack frame" ) ;
946966
947967 if mir. arg_decls . len ( ) == 2 {
948968 // start function
949969 let ptr_size = ecx. memory ( ) . pointer_size ( ) ;
950- let nargs = ecx. memory_mut ( ) . allocate ( ptr_size) ;
970+ let nargs = ecx. memory_mut ( ) . allocate ( ptr_size) . expect ( "can't allocate memory for nargs" ) ;
951971 ecx. memory_mut ( ) . write_usize ( nargs, 0 ) . unwrap ( ) ;
952- let args = ecx. memory_mut ( ) . allocate ( ptr_size) ;
972+ let args = ecx. memory_mut ( ) . allocate ( ptr_size) . expect ( "can't allocate memory for arg pointer" ) ;
953973 ecx. memory_mut ( ) . write_usize ( args, 0 ) . unwrap ( ) ;
954974 ecx. frame_mut ( ) . locals [ 0 ] = nargs;
955975 ecx. frame_mut ( ) . locals [ 1 ] = args;
956976 }
957977
958- loop {
978+ for _ in 0 ..step_limit {
959979 match ecx. step ( ) {
960980 Ok ( true ) => { }
961- Ok ( false ) => break ,
981+ Ok ( false ) => return ,
962982 // FIXME: diverging functions can end up here in some future miri
963983 Err ( e) => {
964984 report ( tcx, & ecx, e) ;
965- break ;
985+ return ;
966986 }
967987 }
968988 }
989+ report ( tcx, & ecx, EvalError :: ExecutionTimeLimitReached ) ;
969990}
970991
971992fn report ( tcx : TyCtxt , ecx : & EvalContext , e : EvalError ) {
0 commit comments