From 9cb8f41ec93ccc83a866088e2f3e5a289c7d3970 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 10 Feb 2021 17:39:38 -0800 Subject: [PATCH] Prevent testsuite from loading config out of sandbox. --- src/bin/cargo/commands/install.rs | 1 + src/cargo/core/workspace.rs | 2 +- src/cargo/ops/cargo_new.rs | 2 +- src/cargo/util/config/mod.rs | 13 ++++++++++++- src/cargo/util/important_paths.rs | 2 +- src/cargo/util/paths.rs | 12 ++++++++---- tests/testsuite/config.rs | 1 + 7 files changed, 25 insertions(+), 8 deletions(-) diff --git a/src/bin/cargo/commands/install.rs b/src/bin/cargo/commands/install.rs index 34ce25b563c..0c36acb648f 100644 --- a/src/bin/cargo/commands/install.rs +++ b/src/bin/cargo/commands/install.rs @@ -78,6 +78,7 @@ pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult { if let Some(path) = args.value_of_path("path", config) { config.reload_rooted_at(path)?; } else { + // TODO: Consider calling set_search_stop_path(home). config.reload_rooted_at(config.home().clone().into_path_unlocked())?; } diff --git a/src/cargo/core/workspace.rs b/src/cargo/core/workspace.rs index e78814233b4..864cef730ed 100644 --- a/src/cargo/core/workspace.rs +++ b/src/cargo/core/workspace.rs @@ -461,7 +461,7 @@ impl<'cfg> Workspace<'cfg> { } } - for path in paths::ancestors(manifest_path).skip(2) { + for path in paths::ancestors(manifest_path, None).skip(2) { if path.ends_with("target/package") { break; } diff --git a/src/cargo/ops/cargo_new.rs b/src/cargo/ops/cargo_new.rs index 083a139080c..4ade5d3dd90 100644 --- a/src/cargo/ops/cargo_new.rs +++ b/src/cargo/ops/cargo_new.rs @@ -872,7 +872,7 @@ fn find_tests_git_config(path: &Path) -> Option { // Don't escape the test sandbox when looking for a git repository. // NOTE: libgit2 has support to define the path ceiling in // git_repository_discover, but the git2 bindings do not expose that. - for path in paths::ancestors(path) { + for path in paths::ancestors(path, None) { if let Ok(repo) = GitRepository::open(path) { return Some(repo.config().expect("test repo should have valid config")); } diff --git a/src/cargo/util/config/mod.rs b/src/cargo/util/config/mod.rs index 3302a027e8c..28a1269bbb5 100644 --- a/src/cargo/util/config/mod.rs +++ b/src/cargo/util/config/mod.rs @@ -132,6 +132,8 @@ pub struct Config { cli_config: Option>, /// The current working directory of cargo cwd: PathBuf, + /// Directory where config file searching should stop (inclusive). + search_stop_path: Option, /// The location of the cargo executable (path to current process) cargo_exe: LazyCell, /// The location of the rustdoc executable @@ -218,6 +220,7 @@ impl Config { home_path: Filesystem::new(homedir), shell: RefCell::new(shell), cwd, + search_stop_path: None, values: LazyCell::new(), cli_config: None, cargo_exe: LazyCell::new(), @@ -422,6 +425,14 @@ impl Config { } } + /// Sets the path where ancestor config file searching will stop. The + /// given path is included, but its ancestors are not. + pub fn set_search_stop_path>(&mut self, path: P) { + let path = path.into(); + debug_assert!(self.cwd.starts_with(&path)); + self.search_stop_path = Some(path); + } + /// Reloads on-disk configuration values, starting at the given path and /// walking up its ancestors. pub fn reload_rooted_at>(&mut self, path: P) -> CargoResult<()> { @@ -1028,7 +1039,7 @@ impl Config { { let mut stash: HashSet = HashSet::new(); - for current in paths::ancestors(pwd) { + for current in paths::ancestors(pwd, self.search_stop_path.as_deref()) { if let Some(path) = self.get_file_path(¤t.join(".cargo"), "config", true)? { walk(&path)?; stash.insert(path); diff --git a/src/cargo/util/important_paths.rs b/src/cargo/util/important_paths.rs index 572194c0a0a..a03cbcc8223 100644 --- a/src/cargo/util/important_paths.rs +++ b/src/cargo/util/important_paths.rs @@ -5,7 +5,7 @@ use std::path::{Path, PathBuf}; /// Finds the root `Cargo.toml`. pub fn find_root_manifest_for_wd(cwd: &Path) -> CargoResult { let file = "Cargo.toml"; - for current in paths::ancestors(cwd) { + for current in paths::ancestors(cwd, None) { let manifest = current.join(file); if manifest.exists() { return Ok(manifest); diff --git a/src/cargo/util/paths.rs b/src/cargo/util/paths.rs index 4a3e6cb103d..5cbea3a1ad9 100644 --- a/src/cargo/util/paths.rs +++ b/src/cargo/util/paths.rs @@ -306,8 +306,8 @@ pub fn bytes2path(bytes: &[u8]) -> CargoResult { } } -pub fn ancestors(path: &Path) -> PathAncestors<'_> { - PathAncestors::new(path) +pub fn ancestors<'a>(path: &'a Path, stop_root_at: Option<&Path>) -> PathAncestors<'a> { + PathAncestors::new(path, stop_root_at) } pub struct PathAncestors<'a> { @@ -316,11 +316,15 @@ pub struct PathAncestors<'a> { } impl<'a> PathAncestors<'a> { - fn new(path: &Path) -> PathAncestors<'_> { + fn new(path: &'a Path, stop_root_at: Option<&Path>) -> PathAncestors<'a> { + let stop_at = env::var("__CARGO_TEST_ROOT") + .ok() + .map(PathBuf::from) + .or_else(|| stop_root_at.map(|p| p.to_path_buf())); PathAncestors { current: Some(path), //HACK: avoid reading `~/.cargo/config` when testing Cargo itself. - stop_at: env::var("__CARGO_TEST_ROOT").ok().map(PathBuf::from), + stop_at, } } } diff --git a/tests/testsuite/config.rs b/tests/testsuite/config.rs index acf8c45fa31..1b45b65b307 100644 --- a/tests/testsuite/config.rs +++ b/tests/testsuite/config.rs @@ -77,6 +77,7 @@ impl ConfigBuilder { let homedir = paths::home(); let mut config = Config::new(shell, cwd, homedir); config.set_env(self.env.clone()); + config.set_search_stop_path(paths::root()); config.configure( 0, false,