diff --git a/src/cargo/util/context/mod.rs b/src/cargo/util/context/mod.rs index 8ad72329302..9eec5d21804 100644 --- a/src/cargo/util/context/mod.rs +++ b/src/cargo/util/context/mod.rs @@ -687,6 +687,16 @@ impl GlobalContext { } => anyhow!( "unexpected variable `{variable}` in build.build-dir path `{raw_template}`" ), + path::ResolveTemplateError::UnexpectedBracket { bracket_type, raw_template } => { + let (btype, literal) = match bracket_type { + path::BracketType::Opening => ("opening", "{"), + path::BracketType::Closing => ("closing", "}"), + }; + + anyhow!( + "unexpected {btype} bracket `{literal}` in build.build-dir path `{raw_template}`" + ) + } })?; // Check if the target directory is set to an empty string in the config.toml file. diff --git a/src/cargo/util/context/path.rs b/src/cargo/util/context/path.rs index 4fd72cebb7e..3fa318bb8ca 100644 --- a/src/cargo/util/context/path.rs +++ b/src/cargo/util/context/path.rs @@ -58,6 +58,20 @@ impl ConfigRelativePath { }); }; + if value.contains("{") { + return Err(ResolveTemplateError::UnexpectedBracket { + bracket_type: BracketType::Opening, + raw_template: self.0.val.clone(), + }); + } + + if value.contains("}") { + return Err(ResolveTemplateError::UnexpectedBracket { + bracket_type: BracketType::Closing, + raw_template: self.0.val.clone(), + }); + } + Ok(self.0.definition.root(gctx).join(&value)) } @@ -139,4 +153,14 @@ pub enum ResolveTemplateError { variable: String, raw_template: String, }, + UnexpectedBracket { + bracket_type: BracketType, + raw_template: String, + }, +} + +#[derive(Debug)] +pub enum BracketType { + Opening, + Closing, } diff --git a/tests/testsuite/build_dir.rs b/tests/testsuite/build_dir.rs index 7854bdebbb3..d2be7147d43 100644 --- a/tests/testsuite/build_dir.rs +++ b/tests/testsuite/build_dir.rs @@ -684,6 +684,49 @@ fn template_workspace_path_hash_should_handle_symlink() { } } +#[cargo_test] +fn template_should_handle_reject_unmatched_brackets() { + let p = project() + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + r#" + [build] + build-dir = "foo/{bar" + "#, + ) + .build(); + + p.cargo("build -Z build-dir") + .masquerade_as_nightly_cargo(&["build-dir"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] unexpected opening bracket `{` in build.build-dir path `foo/{bar` + +"#]]) + .run(); + + let p = project() + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + r#" + [build] + build-dir = "foo/}bar" + "#, + ) + .build(); + + p.cargo("build -Z build-dir") + .masquerade_as_nightly_cargo(&["build-dir"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] unexpected closing bracket `}` in build.build-dir path `foo/}bar` + +"#]]) + .run(); +} + fn parse_workspace_manifest_path_hash(hash_dir: &PathBuf) -> PathBuf { // Since the hash will change between test runs simply find the first directories and assume // that is the hash dir. The format is a 2 char directory followed by the remaining hash in the