diff options
| author | bors <bors@rust-lang.org> | 2024-03-24 15:05:14 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-03-24 15:05:14 +0000 |
| commit | 3dfd4c1f4c955e13d5936a3ffa2a19661c97cd07 (patch) | |
| tree | 082edc685a99176ac2fc692666c1a06b0d0f0516 | |
| parent | e265e3d5189513c42d037999d41a696369af9388 (diff) | |
| parent | 142ef764ee3af3cee8d6336ee153a9e3f13fec90 (diff) | |
| download | rust-3dfd4c1f4c955e13d5936a3ffa2a19661c97cd07.tar.gz rust-3dfd4c1f4c955e13d5936a3ffa2a19661c97cd07.zip | |
Auto merge of #16915 - 6d7a:master, r=HKalbasi
fix: Prevent stack overflow in recursive const types In the evaluation of const values of recursive types certain declarations could cause an endless call-loop within the interpreter (hir-ty’s create_memory_map), which would lead to a stack overflow. This commit adds a check that prevents values that contain an address in their value (such as TyKind::Ref) from being allocated at the address they contain. The commit also adds a test for this edge case.
| -rw-r--r-- | crates/hir-ty/src/consteval/tests.rs | 27 | ||||
| -rw-r--r-- | crates/hir-ty/src/mir/eval.rs | 51 |
2 files changed, 72 insertions, 6 deletions
diff --git a/crates/hir-ty/src/consteval/tests.rs b/crates/hir-ty/src/consteval/tests.rs index 98384c47490..d1ffd5046c3 100644 --- a/crates/hir-ty/src/consteval/tests.rs +++ b/crates/hir-ty/src/consteval/tests.rs @@ -2825,3 +2825,30 @@ fn unsized_local() { |e| matches!(e, ConstEvalError::MirLowerError(MirLowerError::UnsizedTemporary(_))), ); } + +#[test] +fn recursive_adt() { + check_fail( + r#" + //- minicore: coerce_unsized, index, slice + pub enum TagTree { + Leaf, + Choice(&'static [TagTree]), + } + const GOAL: TagTree = { + const TAG_TREE: TagTree = TagTree::Choice(&[ + { + const VARIANT_TAG_TREE: TagTree = TagTree::Choice( + &[ + TagTree::Leaf, + ], + ); + VARIANT_TAG_TREE + }, + ]); + TAG_TREE + }; + "#, + |e| matches!(e, ConstEvalError::MirEvalError(MirEvalError::StackOverflow)), + ); +} diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs index fd98141af63..035991b5e7c 100644 --- a/crates/hir-ty/src/mir/eval.rs +++ b/crates/hir-ty/src/mir/eval.rs @@ -1931,7 +1931,11 @@ impl Evaluator<'_> { ty: &Ty, locals: &Locals, mm: &mut ComplexMemoryMap, + stack_depth_limit: usize, ) -> Result<()> { + if stack_depth_limit.checked_sub(1).is_none() { + return Err(MirEvalError::StackOverflow); + } match ty.kind(Interner) { TyKind::Ref(_, _, t) => { let size = this.size_align_of(t, locals)?; @@ -1970,7 +1974,14 @@ impl Evaluator<'_> { if let Some(ty) = check_inner { for i in 0..count { let offset = element_size * i; - rec(this, &b[offset..offset + element_size], ty, locals, mm)?; + rec( + this, + &b[offset..offset + element_size], + ty, + locals, + mm, + stack_depth_limit - 1, + )?; } } } @@ -1984,7 +1995,14 @@ impl Evaluator<'_> { let size = this.size_of_sized(inner, locals, "inner of array")?; for i in 0..len { let offset = i * size; - rec(this, &bytes[offset..offset + size], inner, locals, mm)?; + rec( + this, + &bytes[offset..offset + size], + inner, + locals, + mm, + stack_depth_limit - 1, + )?; } } chalk_ir::TyKind::Tuple(_, subst) => { @@ -1993,7 +2011,14 @@ impl Evaluator<'_> { let ty = ty.assert_ty_ref(Interner); // Tuple only has type argument let offset = layout.fields.offset(id).bytes_usize(); let size = this.layout(ty)?.size.bytes_usize(); - rec(this, &bytes[offset..offset + size], ty, locals, mm)?; + rec( + this, + &bytes[offset..offset + size], + ty, + locals, + mm, + stack_depth_limit - 1, + )?; } } chalk_ir::TyKind::Adt(adt, subst) => match adt.0 { @@ -2008,7 +2033,14 @@ impl Evaluator<'_> { .bytes_usize(); let ty = &field_types[f].clone().substitute(Interner, subst); let size = this.layout(ty)?.size.bytes_usize(); - rec(this, &bytes[offset..offset + size], ty, locals, mm)?; + rec( + this, + &bytes[offset..offset + size], + ty, + locals, + mm, + stack_depth_limit - 1, + )?; } } AdtId::EnumId(e) => { @@ -2027,7 +2059,14 @@ impl Evaluator<'_> { l.fields.offset(u32::from(f.into_raw()) as usize).bytes_usize(); let ty = &field_types[f].clone().substitute(Interner, subst); let size = this.layout(ty)?.size.bytes_usize(); - rec(this, &bytes[offset..offset + size], ty, locals, mm)?; + rec( + this, + &bytes[offset..offset + size], + ty, + locals, + mm, + stack_depth_limit - 1, + )?; } } } @@ -2038,7 +2077,7 @@ impl Evaluator<'_> { Ok(()) } let mut mm = ComplexMemoryMap::default(); - rec(self, bytes, ty, locals, &mut mm)?; + rec(self, bytes, ty, locals, &mut mm, self.stack_depth_limit - 1)?; Ok(mm) } |
