@@ -137,6 +137,7 @@ pub struct Evaluator<'a> {
137
137
/// time of use.
138
138
vtable_map : VTableMap ,
139
139
thread_local_storage : TlsData ,
140
+ random_state : oorandom:: Rand64 ,
140
141
stdout : Vec < u8 > ,
141
142
stderr : Vec < u8 > ,
142
143
layout_cache : RefCell < FxHashMap < Ty , Arc < Layout > > > ,
@@ -147,6 +148,8 @@ pub struct Evaluator<'a> {
147
148
execution_limit : usize ,
148
149
/// An additional limit on stack depth, to prevent stack overflow
149
150
stack_depth_limit : usize ,
151
+ /// Maximum count of bytes that heap and stack can grow
152
+ memory_limit : usize ,
150
153
}
151
154
152
155
#[ derive( Debug , Clone , Copy , PartialEq , Eq , Hash ) ]
@@ -520,13 +523,15 @@ impl Evaluator<'_> {
520
523
thread_local_storage : TlsData :: default ( ) ,
521
524
static_locations : HashMap :: default ( ) ,
522
525
db,
526
+ random_state : oorandom:: Rand64 :: new ( 0 ) ,
523
527
trait_env,
524
528
crate_id,
525
529
stdout : vec ! [ ] ,
526
530
stderr : vec ! [ ] ,
527
531
assert_placeholder_ty_is_unused,
528
532
stack_depth_limit : 100 ,
529
533
execution_limit : 1000_000 ,
534
+ memory_limit : 1000_000_000 , // 2GB, 1GB for stack and 1GB for heap
530
535
layout_cache : RefCell :: new ( HashMap :: default ( ) ) ,
531
536
}
532
537
}
@@ -938,6 +943,11 @@ impl Evaluator<'_> {
938
943
} ;
939
944
locals. ptr = locals_ptr;
940
945
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
+ }
941
951
self . stack . extend ( iter:: repeat ( 0 ) . take ( stack_size) ) ;
942
952
Ok ( ( locals, prev_stack_pointer) )
943
953
}
@@ -1180,7 +1190,7 @@ impl Evaluator<'_> {
1180
1190
let Some ( ( size, align) ) = self . size_align_of ( ty, locals) ? else {
1181
1191
not_supported ! ( "unsized box initialization" ) ;
1182
1192
} ;
1183
- let addr = self . heap_allocate ( size, align) ;
1193
+ let addr = self . heap_allocate ( size, align) ? ;
1184
1194
Owned ( addr. to_bytes ( ) )
1185
1195
}
1186
1196
Rvalue :: CopyForDeref ( _) => not_supported ! ( "copy for deref" ) ,
@@ -1565,7 +1575,7 @@ impl Evaluator<'_> {
1565
1575
ConstScalar :: Bytes ( v, memory_map) => {
1566
1576
let mut v: Cow < ' _ , [ u8 ] > = Cow :: Borrowed ( v) ;
1567
1577
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) ? ;
1569
1579
self . write_memory ( addr, b) ?;
1570
1580
Ok ( addr. to_usize ( ) )
1571
1581
} ) ?;
@@ -1580,7 +1590,7 @@ impl Evaluator<'_> {
1580
1590
return Err ( MirEvalError :: InvalidConst ( konst. clone ( ) ) ) ;
1581
1591
}
1582
1592
}
1583
- let addr = self . heap_allocate ( size, align) ;
1593
+ let addr = self . heap_allocate ( size, align) ? ;
1584
1594
self . write_memory ( addr, & v) ?;
1585
1595
self . patch_addresses ( & patch_map, & memory_map. vtable , addr, ty, locals) ?;
1586
1596
Interval :: new ( addr, size)
@@ -1683,13 +1693,19 @@ impl Evaluator<'_> {
1683
1693
}
1684
1694
}
1685
1695
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
+ }
1687
1700
while self . heap . len ( ) % align != 0 {
1688
1701
self . heap . push ( 0 ) ;
1689
1702
}
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
+ }
1690
1706
let pos = self . heap . len ( ) ;
1691
1707
self . heap . extend ( iter:: repeat ( 0 ) . take ( size) ) ;
1692
- Address :: Heap ( pos)
1708
+ Ok ( Address :: Heap ( pos) )
1693
1709
}
1694
1710
1695
1711
fn detect_fn_trait ( & self , def : FunctionId ) -> Option < FnTrait > {
@@ -2200,7 +2216,7 @@ impl Evaluator<'_> {
2200
2216
) ?;
2201
2217
// FIXME: there is some leak here
2202
2218
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 ) ? ;
2204
2220
self . write_memory ( addr, & result) ?;
2205
2221
IntervalAndTy { interval : Interval { addr, size } , ty }
2206
2222
} ;
@@ -2235,10 +2251,10 @@ impl Evaluator<'_> {
2235
2251
let Some ( ( size, align) ) = self . size_align_of ( & ty, locals) ? else {
2236
2252
not_supported ! ( "unsized extern static" ) ;
2237
2253
} ;
2238
- let addr = self . heap_allocate ( size, align) ;
2254
+ let addr = self . heap_allocate ( size, align) ? ;
2239
2255
Interval :: new ( addr, size)
2240
2256
} ;
2241
- let addr = self . heap_allocate ( self . ptr_size ( ) , self . ptr_size ( ) ) ;
2257
+ let addr = self . heap_allocate ( self . ptr_size ( ) , self . ptr_size ( ) ) ? ;
2242
2258
self . write_memory ( addr, & result. addr . to_bytes ( ) ) ?;
2243
2259
self . static_locations . insert ( st, addr) ;
2244
2260
Ok ( addr)
@@ -2398,11 +2414,11 @@ pub fn render_const_using_debug_impl(
2398
2414
not_supported ! ( "core::fmt::Debug::fmt not found" ) ;
2399
2415
} ;
2400
2416
// 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 ( ) ) ? ;
2402
2418
// a2 = &[::core::fmt::ArgumentV1::new(&(THE_CONST), ::core::fmt::Debug::fmt)]
2403
2419
// FIXME: we should call the said function, but since its name is going to break in the next rustc version
2404
2420
// 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 ( ) ) ? ;
2406
2422
evaluator. write_memory ( a2, & data. addr . to_bytes ( ) ) ?;
2407
2423
let debug_fmt_fn_ptr = evaluator. vtable_map . id ( TyKind :: FnDef (
2408
2424
db. intern_callable_def ( debug_fmt_fn. into ( ) ) . into ( ) ,
@@ -2412,7 +2428,7 @@ pub fn render_const_using_debug_impl(
2412
2428
evaluator. write_memory ( a2. offset ( evaluator. ptr_size ( ) ) , & debug_fmt_fn_ptr. to_le_bytes ( ) ) ?;
2413
2429
// a3 = ::core::fmt::Arguments::new_v1(a1, a2)
2414
2430
// 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 ( ) ) ? ;
2416
2432
evaluator. write_memory ( a3. offset ( 2 * evaluator. ptr_size ( ) ) , & a1. to_bytes ( ) ) ?;
2417
2433
evaluator. write_memory ( a3. offset ( 3 * evaluator. ptr_size ( ) ) , & [ 1 ] ) ?;
2418
2434
evaluator. write_memory ( a3. offset ( 4 * evaluator. ptr_size ( ) ) , & a2. to_bytes ( ) ) ?;
0 commit comments