Prevent testsuite from loading config out of sandbox.

This commit is contained in:
Eric Huss 2021-02-10 17:39:38 -08:00
parent ab64d1393b
commit 9cb8f41ec9
7 changed files with 25 additions and 8 deletions

View File

@ -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())?;
}

View File

@ -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;
}

View File

@ -872,7 +872,7 @@ fn find_tests_git_config(path: &Path) -> Option<GitConfig> {
// 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"));
}

View File

@ -132,6 +132,8 @@ pub struct Config {
cli_config: Option<Vec<String>>,
/// The current working directory of cargo
cwd: PathBuf,
/// Directory where config file searching should stop (inclusive).
search_stop_path: Option<PathBuf>,
/// The location of the cargo executable (path to current process)
cargo_exe: LazyCell<PathBuf>,
/// 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<P: Into<PathBuf>>(&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<P: AsRef<Path>>(&mut self, path: P) -> CargoResult<()> {
@ -1028,7 +1039,7 @@ impl Config {
{
let mut stash: HashSet<PathBuf> = 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(&current.join(".cargo"), "config", true)? {
walk(&path)?;
stash.insert(path);

View File

@ -5,7 +5,7 @@ use std::path::{Path, PathBuf};
/// Finds the root `Cargo.toml`.
pub fn find_root_manifest_for_wd(cwd: &Path) -> CargoResult<PathBuf> {
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);

View File

@ -306,8 +306,8 @@ pub fn bytes2path(bytes: &[u8]) -> CargoResult<PathBuf> {
}
}
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,
}
}
}

View File

@ -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,