@@ -137,6 +137,7 @@ pub struct Evaluator<'a> {
137137 /// time of use.
138138 vtable_map : VTableMap ,
139139 thread_local_storage : TlsData ,
140+ random_state : oorandom:: Rand64 ,
140141 stdout : Vec < u8 > ,
141142 stderr : Vec < u8 > ,
142143 layout_cache : RefCell < FxHashMap < Ty , Arc < Layout > > > ,
@@ -147,6 +148,8 @@ pub struct Evaluator<'a> {
147148 execution_limit : usize ,
148149 /// An additional limit on stack depth, to prevent stack overflow
149150 stack_depth_limit : usize ,
151+ /// Maximum count of bytes that heap and stack can grow
152+ memory_limit : usize ,
150153}
151154
152155#[ derive( Debug , Clone , Copy , PartialEq , Eq , Hash ) ]
@@ -520,13 +523,15 @@ impl Evaluator<'_> {
520523 thread_local_storage : TlsData :: default ( ) ,
521524 static_locations : HashMap :: default ( ) ,
522525 db,
526+ random_state : oorandom:: Rand64 :: new ( 0 ) ,
523527 trait_env,
524528 crate_id,
525529 stdout : vec ! [ ] ,
526530 stderr : vec ! [ ] ,
527531 assert_placeholder_ty_is_unused,
528532 stack_depth_limit : 100 ,
529533 execution_limit : 1000_000 ,
534+ memory_limit : 1000_000_000 , // 2GB, 1GB for stack and 1GB for heap
530535 layout_cache : RefCell :: new ( HashMap :: default ( ) ) ,
531536 }
532537 }
@@ -938,6 +943,11 @@ impl Evaluator<'_> {
938943 } ;
939944 locals. ptr = locals_ptr;
940945 let prev_stack_pointer = self . stack . len ( ) ;
946+ if stack_size > self . memory_limit {
947+ return Err ( MirEvalError :: Panic ( format ! (
948+ "Stack overflow. Tried to grow stack to {stack_size} bytes"
949+ ) ) ) ;
950+ }
941951 self . stack . extend ( iter:: repeat ( 0 ) . take ( stack_size) ) ;
942952 Ok ( ( locals, prev_stack_pointer) )
943953 }
@@ -1180,7 +1190,7 @@ impl Evaluator<'_> {
11801190 let Some ( ( size, align) ) = self . size_align_of ( ty, locals) ? else {
11811191 not_supported ! ( "unsized box initialization" ) ;
11821192 } ;
1183- let addr = self . heap_allocate ( size, align) ;
1193+ let addr = self . heap_allocate ( size, align) ? ;
11841194 Owned ( addr. to_bytes ( ) )
11851195 }
11861196 Rvalue :: CopyForDeref ( _) => not_supported ! ( "copy for deref" ) ,
@@ -1565,7 +1575,7 @@ impl Evaluator<'_> {
15651575 ConstScalar :: Bytes ( v, memory_map) => {
15661576 let mut v: Cow < ' _ , [ u8 ] > = Cow :: Borrowed ( v) ;
15671577 let patch_map = memory_map. transform_addresses ( |b, align| {
1568- let addr = self . heap_allocate ( b. len ( ) , align) ;
1578+ let addr = self . heap_allocate ( b. len ( ) , align) ? ;
15691579 self . write_memory ( addr, b) ?;
15701580 Ok ( addr. to_usize ( ) )
15711581 } ) ?;
@@ -1580,7 +1590,7 @@ impl Evaluator<'_> {
15801590 return Err ( MirEvalError :: InvalidConst ( konst. clone ( ) ) ) ;
15811591 }
15821592 }
1583- let addr = self . heap_allocate ( size, align) ;
1593+ let addr = self . heap_allocate ( size, align) ? ;
15841594 self . write_memory ( addr, & v) ?;
15851595 self . patch_addresses ( & patch_map, & memory_map. vtable , addr, ty, locals) ?;
15861596 Interval :: new ( addr, size)
@@ -1683,13 +1693,19 @@ impl Evaluator<'_> {
16831693 }
16841694 }
16851695
1686- fn heap_allocate ( & mut self , size : usize , align : usize ) -> Address {
1696+ fn heap_allocate ( & mut self , size : usize , align : usize ) -> Result < Address > {
1697+ if !align. is_power_of_two ( ) || align > 10000 {
1698+ return Err ( MirEvalError :: UndefinedBehavior ( format ! ( "Alignment {align} is invalid" ) ) ) ;
1699+ }
16871700 while self . heap . len ( ) % align != 0 {
16881701 self . heap . push ( 0 ) ;
16891702 }
1703+ if size. checked_add ( self . heap . len ( ) ) . map_or ( true , |x| x > self . memory_limit ) {
1704+ return Err ( MirEvalError :: Panic ( format ! ( "Memory allocation of {size} bytes failed" ) ) ) ;
1705+ }
16901706 let pos = self . heap . len ( ) ;
16911707 self . heap . extend ( iter:: repeat ( 0 ) . take ( size) ) ;
1692- Address :: Heap ( pos)
1708+ Ok ( Address :: Heap ( pos) )
16931709 }
16941710
16951711 fn detect_fn_trait ( & self , def : FunctionId ) -> Option < FnTrait > {
@@ -2200,7 +2216,7 @@ impl Evaluator<'_> {
22002216 ) ?;
22012217 // FIXME: there is some leak here
22022218 let size = layout. size . bytes_usize ( ) ;
2203- let addr = self . heap_allocate ( size, layout. align . abi . bytes ( ) as usize ) ;
2219+ let addr = self . heap_allocate ( size, layout. align . abi . bytes ( ) as usize ) ? ;
22042220 self . write_memory ( addr, & result) ?;
22052221 IntervalAndTy { interval : Interval { addr, size } , ty }
22062222 } ;
@@ -2235,10 +2251,10 @@ impl Evaluator<'_> {
22352251 let Some ( ( size, align) ) = self . size_align_of ( & ty, locals) ? else {
22362252 not_supported ! ( "unsized extern static" ) ;
22372253 } ;
2238- let addr = self . heap_allocate ( size, align) ;
2254+ let addr = self . heap_allocate ( size, align) ? ;
22392255 Interval :: new ( addr, size)
22402256 } ;
2241- let addr = self . heap_allocate ( self . ptr_size ( ) , self . ptr_size ( ) ) ;
2257+ let addr = self . heap_allocate ( self . ptr_size ( ) , self . ptr_size ( ) ) ? ;
22422258 self . write_memory ( addr, & result. addr . to_bytes ( ) ) ?;
22432259 self . static_locations . insert ( st, addr) ;
22442260 Ok ( addr)
@@ -2398,11 +2414,11 @@ pub fn render_const_using_debug_impl(
23982414 not_supported ! ( "core::fmt::Debug::fmt not found" ) ;
23992415 } ;
24002416 // a1 = &[""]
2401- let a1 = evaluator. heap_allocate ( evaluator. ptr_size ( ) * 2 , evaluator. ptr_size ( ) ) ;
2417+ let a1 = evaluator. heap_allocate ( evaluator. ptr_size ( ) * 2 , evaluator. ptr_size ( ) ) ? ;
24022418 // a2 = &[::core::fmt::ArgumentV1::new(&(THE_CONST), ::core::fmt::Debug::fmt)]
24032419 // FIXME: we should call the said function, but since its name is going to break in the next rustc version
24042420 // and its ABI doesn't break yet, we put it in memory manually.
2405- let a2 = evaluator. heap_allocate ( evaluator. ptr_size ( ) * 2 , evaluator. ptr_size ( ) ) ;
2421+ let a2 = evaluator. heap_allocate ( evaluator. ptr_size ( ) * 2 , evaluator. ptr_size ( ) ) ? ;
24062422 evaluator. write_memory ( a2, & data. addr . to_bytes ( ) ) ?;
24072423 let debug_fmt_fn_ptr = evaluator. vtable_map . id ( TyKind :: FnDef (
24082424 db. intern_callable_def ( debug_fmt_fn. into ( ) ) . into ( ) ,
@@ -2412,7 +2428,7 @@ pub fn render_const_using_debug_impl(
24122428 evaluator. write_memory ( a2. offset ( evaluator. ptr_size ( ) ) , & debug_fmt_fn_ptr. to_le_bytes ( ) ) ?;
24132429 // a3 = ::core::fmt::Arguments::new_v1(a1, a2)
24142430 // FIXME: similarly, we should call function here, not directly working with memory.
2415- let a3 = evaluator. heap_allocate ( evaluator. ptr_size ( ) * 6 , evaluator. ptr_size ( ) ) ;
2431+ let a3 = evaluator. heap_allocate ( evaluator. ptr_size ( ) * 6 , evaluator. ptr_size ( ) ) ? ;
24162432 evaluator. write_memory ( a3. offset ( 2 * evaluator. ptr_size ( ) ) , & a1. to_bytes ( ) ) ?;
24172433 evaluator. write_memory ( a3. offset ( 3 * evaluator. ptr_size ( ) ) , & [ 1 ] ) ?;
24182434 evaluator. write_memory ( a3. offset ( 4 * evaluator. ptr_size ( ) ) , & a2. to_bytes ( ) ) ?;
0 commit comments