Skip to content

Commit 5fbaf43

Browse files
authored
fix(config): normalize included config paths (#16964)
### What does this PR try to resolve? Extracted from <#16957>. Without normalizing included config paths, `Definition::root()` will do `parent().parent()` on non-normalized paths containing `..` segments. And that will remove `..` and result in wrong path resolution. ### How to test and review this PR? Two tested are added to showcase the buggy behavior, especially `env_relative_path_included_from_upper_level` which was a wrong path resolution.
2 parents 29af5be + e4e6269 commit 5fbaf43

2 files changed

Lines changed: 59 additions & 0 deletions

File tree

src/cargo/util/context/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2347,6 +2347,7 @@ impl ConfigInclude {
23472347
Definition::Environment(_) | Definition::Cli(None) | Definition::BuiltIn => gctx.cwd(),
23482348
}
23492349
.join(&self.path);
2350+
let abs_path = paths::normalize_path(&abs_path);
23502351

23512352
if self.optional && !abs_path.exists() {
23522353
tracing::info!(

tests/testsuite/config_include.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! Tests for `include` config field.
22
33
use crate::prelude::*;
4+
use cargo_test_support::compare::assert_e2e;
45
use cargo_test_support::str;
56

67
use super::config::GlobalContextBuilder;
@@ -587,3 +588,60 @@ Caused by:
587588
"#]],
588589
);
589590
}
591+
592+
#[cargo_test]
593+
fn env_relative_path_included_from_same_level() {
594+
// See https://github.com/rust-lang/cargo/issues/16954
595+
write_config_at(
596+
"foo/.cargo/config.toml",
597+
"
598+
include = ['../../inc/inc.toml']
599+
600+
[env]
601+
INNER = { value = 'inner-val', relative = true }
602+
",
603+
);
604+
write_config_at(
605+
"inc/inc.toml",
606+
"
607+
[env]
608+
OUTER = { value = 'outer-val', relative = true }
609+
",
610+
);
611+
let gctx = GlobalContextBuilder::new().cwd("foo").build();
612+
let env = gctx.env_config().unwrap();
613+
614+
assert_e2e().eq(
615+
env.get("INNER").unwrap().to_str().unwrap(),
616+
str!["[ROOT]/foo/inner-val"],
617+
);
618+
assert_e2e().eq(
619+
env.get("OUTER").unwrap().to_str().unwrap(),
620+
str!["[ROOT]/outer-val"],
621+
);
622+
}
623+
624+
#[cargo_test]
625+
fn env_relative_path_included_from_upper_level() {
626+
// See https://github.com/rust-lang/cargo/issues/16954
627+
write_config_at(
628+
"outer/foo/.cargo/config.toml",
629+
"
630+
include = ['../../inc.toml']
631+
",
632+
);
633+
write_config_at(
634+
"outer/inc.toml",
635+
"
636+
[env]
637+
MY_ENV = { value = 'val', relative = true }
638+
",
639+
);
640+
let gctx = GlobalContextBuilder::new().cwd("outer/foo").build();
641+
let env = gctx.env_config().unwrap();
642+
643+
assert_e2e().eq(
644+
env.get("MY_ENV").unwrap().to_str().unwrap(),
645+
str!["[ROOT]/val"],
646+
);
647+
}

0 commit comments

Comments
 (0)