Handle env var escaping

This commit is contained in:
Alex Crichton 2020-06-29 12:57:09 -07:00
parent a6bf36e0ac
commit 0750a6f504
2 changed files with 43 additions and 4 deletions

View file

@ -1980,11 +1980,14 @@ pub fn parse_rustc_dep_info(rustc_dep_info: &Path) -> CargoResult<RustcDepInfo>
let rest = &line[env_dep_prefix.len()..];
let mut parts = rest.splitn(2, '=');
let env_var = match parts.next() {
Some(s) => s.to_string(),
Some(s) => s,
None => continue,
};
let env_val = parts.next().map(|s| s.to_string());
ret.env.push((env_var, env_val));
let env_val = match parts.next() {
Some(s) => Some(unescape_env(s)?),
None => None,
};
ret.env.push((unescape_env(env_var)?, env_val));
} else if let Some(pos) = line.find(": ") {
if found_deps {
continue;
@ -2005,5 +2008,27 @@ pub fn parse_rustc_dep_info(rustc_dep_info: &Path) -> CargoResult<RustcDepInfo>
}
}
}
Ok(ret)
return Ok(ret);
// rustc tries to fit env var names and values all on a single line, which
// means it needs to escape `\r` and `\n`. The escape syntax used is "\n"
// which means that `\` also needs to be escaped.
fn unescape_env(s: &str) -> CargoResult<String> {
let mut ret = String::with_capacity(s.len());
let mut chars = s.chars();
while let Some(c) = chars.next() {
if c != '\\' {
ret.push(c);
continue;
}
match chars.next() {
Some('\\') => ret.push('\\'),
Some('n') => ret.push('\n'),
Some('r') => ret.push('\r'),
Some(c) => bail!("unknown escape character `{}`", c),
None => bail!("unterminated escape character"),
}
}
Ok(ret)
}
}

View file

@ -2493,6 +2493,7 @@ fn env_in_code_causes_rebuild() {
r#"
fn main() {
println!("{:?}", option_env!("FOO"));
println!("{:?}", option_env!("FOO\nBAR"));
}
"#,
)
@ -2527,6 +2528,19 @@ fn env_in_code_causes_rebuild() {
.env_remove("FOO")
.with_stderr("[FINISHED][..]")
.run();
let interesting = " #!$\nabc\r\\\t\u{8}\r\n";
p.cargo("build").env("FOO", interesting).run();
p.cargo("build")
.env("FOO", interesting)
.with_stderr("[FINISHED][..]")
.run();
p.cargo("build").env("FOO\nBAR", interesting).run();
p.cargo("build")
.env("FOO\nBAR", interesting)
.with_stderr("[FINISHED][..]")
.run();
}
#[cargo_test]