Encode linker arguments as UTF-16 on MSVC platforms

This commit is contained in:
Mark Simulacrum 2018-02-22 16:37:44 -07:00 committed by Alex Crichton
parent bedbad6119
commit 5db73fc6db
3 changed files with 50 additions and 10 deletions

View file

@ -849,7 +849,19 @@ fn exec_linker(sess: &Session, cmd: &mut Command, tmpdir: &Path)
args.push_str("\n");
}
let file = tmpdir.join("linker-arguments");
fs::write(&file, args.as_bytes())?;
let bytes = if sess.target.target.options.is_like_msvc {
let mut out = vec![];
// start the stream with a UTF-16 BOM
for c in vec![0xFEFF].into_iter().chain(args.encode_utf16()) {
// encode in little endian
out.push(c as u8);
out.push((c >> 8) as u8);
}
out
} else {
args.into_bytes()
};
fs::write(&file, &bytes)?;
cmd2.arg(format!("@{}", file.display()));
return cmd2.output();

View file

@ -36,8 +36,11 @@ fn main() {
let ok = tmpdir.join("ok");
let not_ok = tmpdir.join("not_ok");
if env::var("YOU_ARE_A_LINKER").is_ok() {
match env::args().find(|a| a.contains("@")) {
Some(file) => { fs::copy(&file[1..], &ok).unwrap(); }
match env::args_os().find(|a| a.to_string_lossy().contains("@")) {
Some(file) => {
let file = file.to_str().unwrap();
fs::copy(&file[1..], &ok).unwrap();
}
None => { File::create(&not_ok).unwrap(); }
}
return
@ -84,11 +87,23 @@ fn main() {
continue
}
let mut contents = String::new();
File::open(&ok).unwrap().read_to_string(&mut contents).unwrap();
let mut contents = Vec::new();
File::open(&ok).unwrap().read_to_end(&mut contents).unwrap();
for j in 0..i {
assert!(contents.contains(&format!("{}{}", lib_name, j)));
let exp = format!("{}{}", lib_name, j);
let exp = if cfg!(target_env = "msvc") {
let mut out = Vec::with_capacity(exp.len() * 2);
for c in exp.encode_utf16() {
// encode in little endian
out.push(c as u8);
out.push((c >> 8) as u8);
}
out
} else {
exp.into_bytes()
};
assert!(contents.windows(exp.len()).any(|w| w == &exp[..]));
}
break

View file

@ -27,7 +27,8 @@ fn main() {
let tmpdir = PathBuf::from(env::var_os("TMPDIR").unwrap());
let ok = tmpdir.join("ok");
if env::var("YOU_ARE_A_LINKER").is_ok() {
if let Some(file) = env::args().find(|a| a.contains("@")) {
if let Some(file) = env::args_os().find(|a| a.to_string_lossy().contains("@")) {
let file = file.to_str().expect("non-utf8 file argument");
fs::copy(&file[1..], &ok).unwrap();
}
return
@ -76,11 +77,23 @@ fn main() {
continue
}
let mut contents = String::new();
File::open(&ok).unwrap().read_to_string(&mut contents).unwrap();
let mut contents = Vec::new();
File::open(&ok).unwrap().read_to_end(&mut contents).unwrap();
for j in 0..i {
assert!(contents.contains(&format!("{}{}", lib_name, j)));
let exp = format!("{}{}", lib_name, j);
let exp = if cfg!(target_env = "msvc") {
let mut out = Vec::with_capacity(exp.len() * 2);
for c in exp.encode_utf16() {
// encode in little endian
out.push(c as u8);
out.push((c >> 8) as u8);
}
out
} else {
exp.into_bytes()
};
assert!(contents.windows(exp.len()).any(|w| w == &exp[..]));
}
break