From fe1e148a470cf75c988f78e678da98f20ff5dce7 Mon Sep 17 00:00:00 2001 From: Alex Vig Date: Tue, 28 Aug 2018 12:07:58 -0400 Subject: [PATCH] Guard against c3 linearization reentry Previously there were no checks against circular inheritance. So `a` inherits `[b]` and `b` inherits `[a]` would cause stack overflow. Added hashset to track elements already processed. close #3 --- src/main.rs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/main.rs b/src/main.rs index ac390f0..dc9084b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -99,7 +99,7 @@ fn get_prof(prof_name: &str) -> HashMap { } } - let mut prof_names = c3_linearize(fname, &dpath); + let mut prof_names = c3_linearize(fname, &dpath, &std::collections::HashSet::new()); prof_names.reverse(); load_profs(prof_names, &dpath) @@ -143,7 +143,15 @@ fn load_profs(fnames: Vec, dpath: &std::path::PathBuf) -> HashMap Vec { +fn c3_linearize(fname: String, + dpath: &std::path::PathBuf, + seen: &std::collections::HashSet) -> Vec { + +// Can't just use deref coercion: https://stackoverflow.com/a/39149826/1953800 + if seen.contains(&fname) { + panic!("Detected loop in profile inheritance"); + } + let fpath = dpath.join(&fname); let file = fs::File::open(fpath).expect(&format!("could not open profile: {}", fname)); @@ -160,7 +168,7 @@ fn c3_linearize(fname: String, dpath: &std::path::PathBuf) -> Vec { if let Value::String(s) = elem { p.push(s.to_string()); } else { - println!("couldnt parse profile {}", fname); + println!("couldn't parse profile {}", fname); } } p @@ -175,11 +183,13 @@ fn c3_linearize(fname: String, dpath: &std::path::PathBuf) -> Vec { let mut parent_linearizations: Vec> = vec![]; + let mut seen_updated = seen.clone(); + seen_updated.insert(fname.clone()); for mut parent in parents { if !parent.ends_with(".json") { parent.push_str(".json"); } - let lin = c3_linearize(parent, dpath); + let lin = c3_linearize(parent, dpath, &seen_updated); parent_linearizations.push(lin); }