Skip to content

Commit 142ef76

Browse files
committed
fix: Check stack depth to prevent stack overflows in create_memory_map
1 parent 7c1be82 commit 142ef76

File tree

2 files changed

+48
-16
lines changed

2 files changed

+48
-16
lines changed

crates/hir-ty/src/consteval/tests.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2828,7 +2828,7 @@ fn unsized_local() {
28282828

28292829
#[test]
28302830
fn recursive_adt() {
2831-
check_answer(
2831+
check_fail(
28322832
r#"
28332833
//- minicore: coerce_unsized, index, slice
28342834
pub enum TagTree {
@@ -2849,6 +2849,6 @@ fn recursive_adt() {
28492849
TAG_TREE
28502850
};
28512851
"#,
2852-
|b, _| assert_eq!(b[0] % 8, 0),
2852+
|e| matches!(e, ConstEvalError::MirEvalError(MirEvalError::StackOverflow)),
28532853
);
28542854
}

crates/hir-ty/src/mir/eval.rs

+46-14
Original file line numberDiff line numberDiff line change
@@ -1710,14 +1710,7 @@ impl Evaluator<'_> {
17101710
}
17111711
ConstScalar::Unknown => not_supported!("evaluating unknown const"),
17121712
};
1713-
let patch_map = memory_map.transform_addresses(|b, mut align| {
1714-
// Prevent recursive addresses is adts and slices
1715-
match ((&b[..b.len() / 2]).try_into(), HEAP_OFFSET.checked_add(align)) {
1716-
(Ok(arr), Some(new_addr)) if usize::from_le_bytes(arr) == new_addr => {
1717-
align *= 2;
1718-
}
1719-
_ => (),
1720-
};
1713+
let patch_map = memory_map.transform_addresses(|b, align| {
17211714
let addr = self.heap_allocate(b.len(), align)?;
17221715
self.write_memory(addr, b)?;
17231716
Ok(addr.to_usize())
@@ -1938,7 +1931,11 @@ impl Evaluator<'_> {
19381931
ty: &Ty,
19391932
locals: &Locals,
19401933
mm: &mut ComplexMemoryMap,
1934+
stack_depth_limit: usize,
19411935
) -> Result<()> {
1936+
if stack_depth_limit.checked_sub(1).is_none() {
1937+
return Err(MirEvalError::StackOverflow);
1938+
}
19421939
match ty.kind(Interner) {
19431940
TyKind::Ref(_, _, t) => {
19441941
let size = this.size_align_of(t, locals)?;
@@ -1977,7 +1974,14 @@ impl Evaluator<'_> {
19771974
if let Some(ty) = check_inner {
19781975
for i in 0..count {
19791976
let offset = element_size * i;
1980-
rec(this, &b[offset..offset + element_size], ty, locals, mm)?;
1977+
rec(
1978+
this,
1979+
&b[offset..offset + element_size],
1980+
ty,
1981+
locals,
1982+
mm,
1983+
stack_depth_limit - 1,
1984+
)?;
19811985
}
19821986
}
19831987
}
@@ -1991,7 +1995,14 @@ impl Evaluator<'_> {
19911995
let size = this.size_of_sized(inner, locals, "inner of array")?;
19921996
for i in 0..len {
19931997
let offset = i * size;
1994-
rec(this, &bytes[offset..offset + size], inner, locals, mm)?;
1998+
rec(
1999+
this,
2000+
&bytes[offset..offset + size],
2001+
inner,
2002+
locals,
2003+
mm,
2004+
stack_depth_limit - 1,
2005+
)?;
19952006
}
19962007
}
19972008
chalk_ir::TyKind::Tuple(_, subst) => {
@@ -2000,7 +2011,14 @@ impl Evaluator<'_> {
20002011
let ty = ty.assert_ty_ref(Interner); // Tuple only has type argument
20012012
let offset = layout.fields.offset(id).bytes_usize();
20022013
let size = this.layout(ty)?.size.bytes_usize();
2003-
rec(this, &bytes[offset..offset + size], ty, locals, mm)?;
2014+
rec(
2015+
this,
2016+
&bytes[offset..offset + size],
2017+
ty,
2018+
locals,
2019+
mm,
2020+
stack_depth_limit - 1,
2021+
)?;
20042022
}
20052023
}
20062024
chalk_ir::TyKind::Adt(adt, subst) => match adt.0 {
@@ -2015,7 +2033,14 @@ impl Evaluator<'_> {
20152033
.bytes_usize();
20162034
let ty = &field_types[f].clone().substitute(Interner, subst);
20172035
let size = this.layout(ty)?.size.bytes_usize();
2018-
rec(this, &bytes[offset..offset + size], ty, locals, mm)?;
2036+
rec(
2037+
this,
2038+
&bytes[offset..offset + size],
2039+
ty,
2040+
locals,
2041+
mm,
2042+
stack_depth_limit - 1,
2043+
)?;
20192044
}
20202045
}
20212046
AdtId::EnumId(e) => {
@@ -2034,7 +2059,14 @@ impl Evaluator<'_> {
20342059
l.fields.offset(u32::from(f.into_raw()) as usize).bytes_usize();
20352060
let ty = &field_types[f].clone().substitute(Interner, subst);
20362061
let size = this.layout(ty)?.size.bytes_usize();
2037-
rec(this, &bytes[offset..offset + size], ty, locals, mm)?;
2062+
rec(
2063+
this,
2064+
&bytes[offset..offset + size],
2065+
ty,
2066+
locals,
2067+
mm,
2068+
stack_depth_limit - 1,
2069+
)?;
20382070
}
20392071
}
20402072
}
@@ -2045,7 +2077,7 @@ impl Evaluator<'_> {
20452077
Ok(())
20462078
}
20472079
let mut mm = ComplexMemoryMap::default();
2048-
rec(self, bytes, ty, locals, &mut mm)?;
2080+
rec(self, bytes, ty, locals, &mut mm, self.stack_depth_limit - 1)?;
20492081
Ok(mm)
20502082
}
20512083

0 commit comments

Comments
 (0)