Skip to content

Commit

Permalink
Encode linker arguments as UTF-16 on MSVC platforms
Browse files Browse the repository at this point in the history
  • Loading branch information
Mark-Simulacrum authored and alexcrichton committed Feb 26, 2018
1 parent bedbad6 commit 5db73fc
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 10 deletions.
14 changes: 13 additions & 1 deletion src/librustc_trans/back/link.rs
Expand Up @@ -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();

Expand Down
25 changes: 20 additions & 5 deletions src/test/run-make/long-linker-command-lines-cmd-exe/foo.rs
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
21 changes: 17 additions & 4 deletions src/test/run-make/long-linker-command-lines/foo.rs
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 5db73fc

Please sign in to comment.