Skip to content

Commit

Permalink
Auto merge of #17412 - davidhewitt:source-loop-cycle-bail, r=Veykril
Browse files Browse the repository at this point in the history
fix: add a breaker to avoid infinite loops from source root cycles

See #17409

This patch prevents infinite looping from cycles by giving up if the number of source roots checked for a config value reaches the total number of source roots.

Alternative more precise options include creating a set of all source roots visited and giving up as soon as a cycle is encountered, but I wasn't sure how costly an allocation would be here for performance.

Can confirm that locally this fixes the problem for me.
  • Loading branch information
bors committed Jun 13, 2024
2 parents fa486e6 + 0cbf900 commit 57e990b
Showing 1 changed file with 9 additions and 0 deletions.
9 changes: 9 additions & 0 deletions crates/rust-analyzer/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2531,13 +2531,22 @@ macro_rules! _impl_for_config_data {
#[allow(non_snake_case)]
$vis fn $field(&self, source_root: Option<SourceRootId>) -> &$ty {
let mut par: Option<SourceRootId> = source_root;
let mut traversals = 0;
while let Some(source_root_id) = par {
par = self.source_root_parent_map.get(&source_root_id).copied();
if let Some((config, _)) = self.ratoml_files.get(&source_root_id) {
if let Some(value) = config.$field.as_ref() {
return value;
}
}
// Prevent infinite loops caused by cycles by giving up when it's
// clear that we must have either visited all source roots or
// encountered a cycle.
traversals += 1;
if traversals >= self.source_root_parent_map.len() {
// i.e. no source root contains the config we're looking for
break;
}
}

if let Some((root_path_ratoml, _)) = self.root_ratoml.as_ref() {
Expand Down

0 comments on commit 57e990b

Please sign in to comment.