From 5db73fc6dbf9e4ee1a498655cb609efdf5fa93ed Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Thu, 22 Feb 2018 16:37:44 -0700 Subject: [PATCH] Encode linker arguments as UTF-16 on MSVC platforms --- src/librustc_trans/back/link.rs | 14 ++++++++++- .../long-linker-command-lines-cmd-exe/foo.rs | 25 +++++++++++++++---- .../run-make/long-linker-command-lines/foo.rs | 21 +++++++++++++--- 3 files changed, 50 insertions(+), 10 deletions(-) diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index d7c75dea8d04e..8f308e726865c 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -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(); diff --git a/src/test/run-make/long-linker-command-lines-cmd-exe/foo.rs b/src/test/run-make/long-linker-command-lines-cmd-exe/foo.rs index f9168a82e2259..67d8ad0b67255 100644 --- a/src/test/run-make/long-linker-command-lines-cmd-exe/foo.rs +++ b/src/test/run-make/long-linker-command-lines-cmd-exe/foo.rs @@ -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(¬_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 diff --git a/src/test/run-make/long-linker-command-lines/foo.rs b/src/test/run-make/long-linker-command-lines/foo.rs index e6fd6b653667f..2ac240982afc4 100644 --- a/src/test/run-make/long-linker-command-lines/foo.rs +++ b/src/test/run-make/long-linker-command-lines/foo.rs @@ -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