From a8891ae3ca1f23ef310a91b2e30bac7e08be4aa1 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 11 Jul 2020 18:35:35 +0200 Subject: More tight recursion limit when expanding macros in function bodies cc #4944 cc #5317 This doesn't fully close #4944 -- looks like we hit SO in syntax highlighting, when we use `Semantics::expand_macro`. Seems like we need to place expansion limit on the macro itself (store it as a part of MacroCallId?)! --- crates/ra_hir_def/src/body.rs | 54 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 48 insertions(+), 6 deletions(-) (limited to 'crates/ra_hir_def') diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index 031ffe13f..8c233a717 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs @@ -14,6 +14,7 @@ use ra_db::CrateId; use ra_prof::profile; use ra_syntax::{ast, AstNode, AstPtr}; use rustc_hash::FxHashMap; +use test_utils::mark; pub(crate) use lower::LowerCtx; @@ -42,7 +43,7 @@ pub(crate) struct Expander { current_file_id: HirFileId, ast_id_map: Arc, module: ModuleId, - recursive_limit: usize, + recursion_limit: usize, } impl CfgExpander { @@ -81,7 +82,7 @@ impl Expander { current_file_id, ast_id_map, module, - recursive_limit: 0, + recursion_limit: 0, } } @@ -91,7 +92,9 @@ impl Expander { local_scope: Option<&ItemScope>, macro_call: ast::MacroCall, ) -> Option<(Mark, T)> { - if self.recursive_limit > 1024 { + self.recursion_limit += 1; + if self.recursion_limit > 32 { + mark::hit!(your_stack_belongs_to_me); return None; } @@ -118,8 +121,6 @@ impl Expander { self.cfg_expander.hygiene = Hygiene::new(db.upcast(), file_id); self.current_file_id = file_id; self.ast_id_map = db.ast_id_map(file_id); - self.recursive_limit += 1; - return Some((mark, expr)); } } @@ -134,7 +135,7 @@ impl Expander { self.cfg_expander.hygiene = Hygiene::new(db.upcast(), mark.file_id); self.current_file_id = mark.file_id; self.ast_id_map = mem::take(&mut mark.ast_id_map); - self.recursive_limit -= 1; + self.recursion_limit -= 1; mark.bomb.defuse(); } @@ -311,3 +312,44 @@ impl BodySourceMap { self.field_map[&(expr, field)].clone() } } + +#[cfg(test)] +mod tests { + use ra_db::{fixture::WithFixture, SourceDatabase}; + use test_utils::mark; + + use crate::ModuleDefId; + + use super::*; + + fn lower(ra_fixture: &str) -> Arc { + let (db, file_id) = crate::test_db::TestDB::with_single_file(ra_fixture); + + let krate = db.crate_graph().iter().next().unwrap(); + let def_map = db.crate_def_map(krate); + let module = def_map.modules_for_file(file_id).next().unwrap(); + let module = &def_map[module]; + let fn_def = match module.scope.declarations().next().unwrap() { + ModuleDefId::FunctionId(it) => it, + _ => panic!(), + }; + + db.body(fn_def.into()) + } + + #[test] + fn your_stack_belongs_to_me() { + mark::check!(your_stack_belongs_to_me); + lower( + r" +macro_rules! n_nuple { + ($e:tt) => (); + ($($rest:tt)*) => {{ + (n_nuple!($($rest)*)None,) + }}; +} +fn main() { n_nuple!(1,2,3); } +", + ); + } +} -- cgit v1.2.3