Skip to content

Commit 3f91e93

Browse files
authored
Merge pull request #1599 from euclio/non-utf8-args
allow non-utf8 arguments to proxies
2 parents b47800c + ae1ca03 commit 3f91e93

File tree

5 files changed

+114
-17
lines changed

5 files changed

+114
-17
lines changed

src/rustup-cli/proxy_mode.rs

+6-8
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pub fn main() -> Result<()> {
1515
let ExitCode(c) = {
1616
let _setup = job::setup();
1717

18-
let mut args = env::args();
18+
let mut args = env::args_os();
1919

2020
let arg0 = args.next().map(PathBuf::from);
2121
let arg0 = arg0
@@ -26,13 +26,11 @@ pub fn main() -> Result<()> {
2626

2727
// Check for a toolchain specifier.
2828
let arg1 = args.next();
29-
let toolchain = arg1.as_ref().and_then(|arg1| {
30-
if arg1.starts_with('+') {
31-
Some(&arg1[1..])
32-
} else {
33-
None
34-
}
35-
});
29+
let toolchain_arg = arg1
30+
.as_ref()
31+
.map(|arg| arg.to_string_lossy())
32+
.filter(|arg| arg.starts_with('+'));
33+
let toolchain = toolchain_arg.as_ref().map(|a| &a[1..]);
3634

3735
// Build command args now while we know whether or not to skip arg 1.
3836
let cmd_args: Vec<_> = if toolchain.is_none() {

src/rustup-mock/src/clitools.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use std::cell::RefCell;
1010
use std::collections::HashMap;
1111
use std::env;
1212
use std::env::consts::EXE_SUFFIX;
13+
use std::ffi::OsStr;
1314
use std::fs::{self, File};
1415
use std::io::{self, Read, Write};
1516
use std::mem;
@@ -296,7 +297,11 @@ pub struct SanitizedOutput {
296297
pub stderr: String,
297298
}
298299

299-
pub fn cmd(config: &Config, name: &str, args: &[&str]) -> Command {
300+
pub fn cmd<I, A>(config: &Config, name: &str, args: I) -> Command
301+
where
302+
I: IntoIterator<Item = A>,
303+
A: AsRef<OsStr>,
304+
{
300305
let exe_path = config.exedir.join(format!("{}{}", name, EXE_SUFFIX));
301306
let mut cmd = Command::new(exe_path);
302307
cmd.args(args);
@@ -340,7 +345,11 @@ pub fn env(config: &Config, cmd: &mut Command) {
340345
cmd.env("RUSTUP_INIT_SKIP_PATH_CHECK", "yes");
341346
}
342347

343-
pub fn run(config: &Config, name: &str, args: &[&str], env: &[(&str, &str)]) -> SanitizedOutput {
348+
pub fn run<I, A>(config: &Config, name: &str, args: I, env: &[(&str, &str)]) -> SanitizedOutput
349+
where
350+
I: IntoIterator<Item = A>,
351+
A: AsRef<OsStr>,
352+
{
344353
let mut cmd = cmd(config, name, args);
345354
for env in env {
346355
cmd.env(env.0, env.1);

src/rustup-mock/src/mock_bin_src.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ use std::path::{PathBuf, Path};
66
use std::process::Command;
77

88
fn main() {
9-
let mut args = env::args().skip(1);
10-
match args.next().as_ref().map(|s| &**s) {
9+
let mut args = env::args_os().skip(1);
10+
match args.next().as_ref().and_then(|s| s.to_str()) {
1111
Some("--version") => {
1212
let me = env::current_exe().unwrap();
1313
let mut version_file = PathBuf::from(format!("{}.version", me.display()));
@@ -62,6 +62,12 @@ fn main() {
6262
let rustc = &format!("rustc{}", EXE_SUFFIX);
6363
Command::new(rustc).arg("--version").status().unwrap();
6464
}
65+
Some("--echo-args") => {
66+
let mut out = io::stderr();
67+
for arg in args {
68+
writeln!(out, "{}", arg.to_string_lossy()).unwrap();
69+
}
70+
}
6571
_ => panic!("bad mock proxy commandline"),
6672
}
6773
}

tests/cli-misc.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ fn smoke_test() {
4141
#[test]
4242
fn no_colors_in_piped_error_output() {
4343
setup(&|config| {
44-
let out = run(config, "rustc", &[], &[]);
44+
let args: Vec<&str> = vec![];
45+
let out = run(config, "rustc", &args, &[]);
4546
assert!(!out.ok);
4647
assert!(!out.stderr.contains("\u{1b}"));
4748
});
@@ -50,7 +51,8 @@ fn no_colors_in_piped_error_output() {
5051
#[test]
5152
fn rustc_with_bad_rustup_toolchain_env_var() {
5253
setup(&|config| {
53-
let out = run(config, "rustc", &[], &[("RUSTUP_TOOLCHAIN", "bogus")]);
54+
let args: Vec<&str> = vec![];
55+
let out = run(config, "rustc", &args, &[("RUSTUP_TOOLCHAIN", "bogus")]);
5456
assert!(!out.ok);
5557
assert!(out.stderr.contains("toolchain 'bogus' is not installed"));
5658
});
@@ -677,10 +679,11 @@ fn install_stops_if_rustc_exists() {
677679
let temp_dir_path = temp_dir.path().to_str().unwrap();
678680

679681
setup(&|config| {
682+
let args: Vec<&str> = vec![];
680683
let out = run(
681684
config,
682685
"rustup-init",
683-
&[],
686+
&args,
684687
&[
685688
("RUSTUP_INIT_SKIP_PATH_CHECK", "no"),
686689
("PATH", &temp_dir_path),
@@ -705,10 +708,11 @@ fn install_stops_if_cargo_exists() {
705708
let temp_dir_path = temp_dir.path().to_str().unwrap();
706709

707710
setup(&|config| {
711+
let args: Vec<&str> = vec![];
708712
let out = run(
709713
config,
710714
"rustup-init",
711-
&[],
715+
&args,
712716
&[
713717
("RUSTUP_INIT_SKIP_PATH_CHECK", "no"),
714718
("PATH", &temp_dir_path),

tests/cli-rustup.rs

+81-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ extern crate rustup_utils;
66
extern crate tempdir;
77

88
use rustup_mock::clitools::{
9-
self, expect_err, expect_ok, expect_ok_ex, expect_stderr_ok, expect_stdout_ok,
9+
self, expect_err, expect_ok, expect_ok_ex, expect_stderr_ok, expect_stdout_ok, run,
1010
set_current_dist_date, this_host_triple, Config, Scenario,
1111
};
1212
use rustup_utils::raw;
@@ -1557,3 +1557,83 @@ fn docs_with_path() {
15571557
assert!(String::from_utf8(out.stdout).unwrap().contains("nightly"));
15581558
});
15591559
}
1560+
1561+
#[cfg(unix)]
1562+
#[test]
1563+
fn non_utf8_arg() {
1564+
use std::ffi::OsStr;
1565+
use std::os::unix::ffi::OsStrExt;
1566+
1567+
setup(&|config| {
1568+
expect_ok(config, &["rustup", "default", "nightly"]);
1569+
let out = run(
1570+
config,
1571+
"rustc",
1572+
&[
1573+
OsStr::new("--echo-args"),
1574+
OsStr::new("echoed non-utf8 arg:"),
1575+
OsStr::from_bytes(b"\xc3\x28"),
1576+
],
1577+
&[("RUST_BACKTRACE", "1")],
1578+
);
1579+
assert!(out.stderr.contains("echoed non-utf8 arg"));
1580+
});
1581+
}
1582+
1583+
#[cfg(windows)]
1584+
#[test]
1585+
fn non_utf8_arg() {
1586+
use std::ffi::OsString;
1587+
use std::os::windows::ffi::OsStringExt;
1588+
1589+
setup(&|config| {
1590+
expect_ok(config, &["rustup", "default", "nightly"]);
1591+
let out = run(
1592+
config,
1593+
"rustc",
1594+
&[
1595+
OsString::from("--echo-args".to_string()),
1596+
OsString::from("echoed non-utf8 arg:".to_string()),
1597+
OsString::from_wide(&[0xd801, 0xd801]),
1598+
],
1599+
&[("RUST_BACKTRACE", "1")],
1600+
);
1601+
assert!(out.stderr.contains("echoed non-utf8 arg"));
1602+
});
1603+
}
1604+
1605+
#[cfg(unix)]
1606+
#[test]
1607+
fn non_utf8_toolchain() {
1608+
use std::ffi::OsStr;
1609+
use std::os::unix::ffi::OsStrExt;
1610+
1611+
setup(&|config| {
1612+
expect_ok(config, &["rustup", "default", "nightly"]);
1613+
let out = run(
1614+
config,
1615+
"rustc",
1616+
&[OsStr::from_bytes(b"+\xc3\x28")],
1617+
&[("RUST_BACKTRACE", "1")],
1618+
);
1619+
assert!(out.stderr.contains("toolchain '�(' is not installed"));
1620+
});
1621+
}
1622+
1623+
#[cfg(windows)]
1624+
#[test]
1625+
fn non_utf8_toolchain() {
1626+
use std::ffi::OsString;
1627+
use std::os::windows::ffi::OsStringExt;
1628+
1629+
setup(&|config| {
1630+
expect_ok(config, &["rustup", "default", "nightly"]);
1631+
let out = run(
1632+
config,
1633+
"rustc",
1634+
&[OsString::from_wide(&[u16::from('+' as u8), 0xd801, 0xd801])],
1635+
&[("RUST_BACKTRACE", "1")],
1636+
);
1637+
assert!(out.stderr.contains("toolchain '��' is not installed"));
1638+
});
1639+
}

0 commit comments

Comments
 (0)