Skip to content

Commit

Permalink
Guard against c3 linearization reentry
Browse files Browse the repository at this point in the history
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
  • Loading branch information
jalexvig committed Aug 28, 2018
1 parent ac01823 commit fe1e148
Showing 1 changed file with 14 additions and 4 deletions.
18 changes: 14 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ fn get_prof(prof_name: &str) -> HashMap<String, Value> {
}
}

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)
Expand Down Expand Up @@ -143,7 +143,15 @@ fn load_profs(fnames: Vec<String>, dpath: &std::path::PathBuf) -> HashMap<String
res
}

fn c3_linearize(fname: String, dpath: &std::path::PathBuf) -> Vec<String> {
fn c3_linearize(fname: String,
dpath: &std::path::PathBuf,
seen: &std::collections::HashSet<String>) -> Vec<String> {

// 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));
Expand All @@ -160,7 +168,7 @@ fn c3_linearize(fname: String, dpath: &std::path::PathBuf) -> Vec<String> {
if let Value::String(s) = elem {
p.push(s.to_string());
} else {
println!("couldnt parse profile {}", fname);
println!("couldn't parse profile {}", fname);
}
}
p
Expand All @@ -175,11 +183,13 @@ fn c3_linearize(fname: String, dpath: &std::path::PathBuf) -> Vec<String> {

let mut parent_linearizations: Vec<Vec<String>> = 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);
}

Expand Down

0 comments on commit fe1e148

Please sign in to comment.