diff options
| author | 6d7a <westphal@consider-it.de> | 2024-03-21 22:57:21 +0100 |
|---|---|---|
| committer | 6d7a <westphal@consider-it.de> | 2024-03-21 22:57:21 +0100 |
| commit | 7c1be82cd9abe195205bee476c546a7645632af3 (patch) | |
| tree | 0d9ee80845ac303f5684f4093304fcc257844e68 | |
| parent | 7ef7f442fc34b5eadb1c6ad6433bd6d0c51b056b (diff) | |
| download | rust-7c1be82cd9abe195205bee476c546a7645632af3.tar.gz rust-7c1be82cd9abe195205bee476c546a7645632af3.zip | |
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 | 9 |
2 files changed, 35 insertions, 1 deletions
diff --git a/crates/hir-ty/src/consteval/tests.rs b/crates/hir-ty/src/consteval/tests.rs index 98384c47490..9199663be12 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_answer( + 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 + }; + "#, + |b, _| assert_eq!(b[0] % 8, 0), + ); +} diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs index fd98141af63..90b8092b4b1 100644 --- a/crates/hir-ty/src/mir/eval.rs +++ b/crates/hir-ty/src/mir/eval.rs @@ -1710,7 +1710,14 @@ impl Evaluator<'_> { } ConstScalar::Unknown => not_supported!("evaluating unknown const"), }; - let patch_map = memory_map.transform_addresses(|b, align| { + let patch_map = memory_map.transform_addresses(|b, mut align| { + // Prevent recursive addresses is adts and slices + match ((&b[..b.len() / 2]).try_into(), HEAP_OFFSET.checked_add(align)) { + (Ok(arr), Some(new_addr)) if usize::from_le_bytes(arr) == new_addr => { + align *= 2; + } + _ => (), + }; let addr = self.heap_allocate(b.len(), align)?; self.write_memory(addr, b)?; Ok(addr.to_usize()) |
