Skip to content

Commit 2a0bf2b

Browse files
authored
Fix: Accept non utf-8 characters in compiler and archiver (#998)
* Accept `impl AsRef<Path>` in fn `run*`, `spawn` and `try_wait_on_child` Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com> * Accept non utf-8 path in compiler in `create_compile_object_cmd` Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com> * Accept non utf-8 characters in archiver path Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com> * Remove generics from `spawn` and `try_wait_on_child` They are only used in `Build::compile_objects` with `&Path`, so there is no need to use generics. Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com> * Remove rebundant import of `std::convert::AsRef` Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com> --------- Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
1 parent f6d81ef commit 2a0bf2b

File tree

3 files changed

+54
-32
lines changed

3 files changed

+54
-32
lines changed

src/command_helpers.rs

+34-16
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ fn write_warning(line: &[u8]) {
215215

216216
fn wait_on_child(
217217
cmd: &Command,
218-
program: &str,
218+
program: &Path,
219219
child: &mut Child,
220220
cargo_output: &CargoOutput,
221221
) -> Result<(), Error> {
@@ -227,8 +227,10 @@ fn wait_on_child(
227227
return Err(Error::new(
228228
ErrorKind::ToolExecError,
229229
format!(
230-
"Failed to wait on spawned child process, command {:?} with args {:?}: {}.",
231-
cmd, program, e
230+
"Failed to wait on spawned child process, command {:?} with args {}: {}.",
231+
cmd,
232+
program.display(),
233+
e
232234
),
233235
));
234236
}
@@ -242,8 +244,10 @@ fn wait_on_child(
242244
Err(Error::new(
243245
ErrorKind::ToolExecError,
244246
format!(
245-
"Command {:?} with args {:?} did not execute successfully (status code {}).",
246-
cmd, program, status
247+
"Command {:?} with args {} did not execute successfully (status code {}).",
248+
cmd,
249+
program.display(),
250+
status
247251
),
248252
))
249253
}
@@ -299,18 +303,22 @@ pub(crate) fn objects_from_files(files: &[Arc<Path>], dst: &Path) -> Result<Vec<
299303

300304
pub(crate) fn run(
301305
cmd: &mut Command,
302-
program: &str,
306+
program: impl AsRef<Path>,
303307
cargo_output: &CargoOutput,
304308
) -> Result<(), Error> {
309+
let program = program.as_ref();
310+
305311
let mut child = spawn(cmd, program, cargo_output)?;
306312
wait_on_child(cmd, program, &mut child, cargo_output)
307313
}
308314

309315
pub(crate) fn run_output(
310316
cmd: &mut Command,
311-
program: &str,
317+
program: impl AsRef<Path>,
312318
cargo_output: &CargoOutput,
313319
) -> Result<Vec<u8>, Error> {
320+
let program = program.as_ref();
321+
314322
cmd.stdout(Stdio::piped());
315323

316324
let mut child = spawn(cmd, program, cargo_output)?;
@@ -330,7 +338,7 @@ pub(crate) fn run_output(
330338

331339
pub(crate) fn spawn(
332340
cmd: &mut Command,
333-
program: &str,
341+
program: &Path,
334342
cargo_output: &CargoOutput,
335343
) -> Result<Child, Error> {
336344
struct ResetStderr<'cmd>(&'cmd mut Command);
@@ -358,14 +366,20 @@ for help)"
358366
};
359367
Err(Error::new(
360368
ErrorKind::ToolNotFound,
361-
format!("Failed to find tool. Is `{}` installed?{}", program, extra),
369+
format!(
370+
"Failed to find tool. Is `{}` installed?{}",
371+
program.display(),
372+
extra
373+
),
362374
))
363375
}
364376
Err(e) => Err(Error::new(
365377
ErrorKind::ToolExecError,
366378
format!(
367-
"Command {:?} with args {:?} failed to start: {:?}",
368-
cmd.0, program, e
379+
"Command {:?} with args {} failed to start: {:?}",
380+
cmd.0,
381+
program.display(),
382+
e
369383
),
370384
)),
371385
}
@@ -393,7 +407,7 @@ pub(crate) fn command_add_output_file(
393407
#[cfg(feature = "parallel")]
394408
pub(crate) fn try_wait_on_child(
395409
cmd: &Command,
396-
program: &str,
410+
program: &Path,
397411
child: &mut Child,
398412
stdout: &mut dyn io::Write,
399413
stderr_forwarder: &mut StderrForwarder,
@@ -412,8 +426,10 @@ pub(crate) fn try_wait_on_child(
412426
Err(Error::new(
413427
ErrorKind::ToolExecError,
414428
format!(
415-
"Command {:?} with args {:?} did not execute successfully (status code {}).",
416-
cmd, program, status
429+
"Command {:?} with args {} did not execute successfully (status code {}).",
430+
cmd,
431+
program.display(),
432+
status
417433
),
418434
))
419435
}
@@ -424,8 +440,10 @@ pub(crate) fn try_wait_on_child(
424440
Err(Error::new(
425441
ErrorKind::ToolExecError,
426442
format!(
427-
"Failed to wait on spawned child process, command {:?} with args {:?}: {}.",
428-
cmd, program, e
443+
"Failed to wait on spawned child process, command {:?} with args {}: {}.",
444+
cmd,
445+
program.display(),
446+
e
429447
),
430448
))
431449
}

src/lib.rs

+19-15
Original file line numberDiff line numberDiff line change
@@ -1439,7 +1439,7 @@ impl Build {
14391439

14401440
let pendings = Cell::new(Vec::<(
14411441
Command,
1442-
String,
1442+
Cow<'static, Path>,
14431443
KillOnDrop,
14441444
parallel::job_token::JobToken,
14451445
)>::new());
@@ -1563,7 +1563,10 @@ impl Build {
15631563
Ok(())
15641564
}
15651565

1566-
fn create_compile_object_cmd(&self, obj: &Object) -> Result<(Command, String), Error> {
1566+
fn create_compile_object_cmd(
1567+
&self,
1568+
obj: &Object,
1569+
) -> Result<(Command, Cow<'static, Path>), Error> {
15671570
let asm_ext = AsmFileExt::from_path(&obj.src);
15681571
let is_asm = asm_ext.is_some();
15691572
let target = self.get_target()?;
@@ -1574,7 +1577,8 @@ impl Build {
15741577

15751578
let is_assembler_msvc = msvc && asm_ext == Some(AsmFileExt::DotAsm);
15761579
let (mut cmd, name) = if is_assembler_msvc {
1577-
self.msvc_macro_assembler()?
1580+
let (cmd, name) = self.msvc_macro_assembler()?;
1581+
(cmd, Cow::Borrowed(Path::new(name)))
15781582
} else {
15791583
let mut cmd = compiler.to_command();
15801584
for (a, b) in self.env.iter() {
@@ -1585,9 +1589,9 @@ impl Build {
15851589
compiler
15861590
.path
15871591
.file_name()
1588-
.ok_or_else(|| Error::new(ErrorKind::IOError, "Failed to get compiler path."))?
1589-
.to_string_lossy()
1590-
.into_owned(),
1592+
.ok_or_else(|| Error::new(ErrorKind::IOError, "Failed to get compiler path."))
1593+
.map(PathBuf::from)
1594+
.map(Cow::Owned)?,
15911595
)
15921596
};
15931597
let is_arm = target.contains("aarch64") || target.contains("arm");
@@ -1653,9 +1657,7 @@ impl Build {
16531657
let name = compiler
16541658
.path
16551659
.file_name()
1656-
.ok_or_else(|| Error::new(ErrorKind::IOError, "Failed to get compiler path."))?
1657-
.to_string_lossy()
1658-
.into_owned();
1660+
.ok_or_else(|| Error::new(ErrorKind::IOError, "Failed to get compiler path."))?;
16591661

16601662
Ok(run_output(&mut cmd, &name, &self.cargo_output)?)
16611663
}
@@ -2321,7 +2323,7 @@ impl Build {
23212323
}
23222324
}
23232325

2324-
fn msvc_macro_assembler(&self) -> Result<(Command, String), Error> {
2326+
fn msvc_macro_assembler(&self) -> Result<(Command, &'static str), Error> {
23252327
let target = self.get_target()?;
23262328
let tool = if target.contains("x86_64") {
23272329
"ml64.exe"
@@ -2374,7 +2376,7 @@ impl Build {
23742376
cmd.arg("-safeseh");
23752377
}
23762378

2377-
Ok((cmd, tool.to_string()))
2379+
Ok((cmd, tool))
23782380
}
23792381

23802382
fn assemble(&self, lib_name: &str, dst: &Path, objs: &[Object]) -> Result<(), Error> {
@@ -3026,7 +3028,7 @@ impl Build {
30263028
}
30273029
}
30283030

3029-
fn get_ar(&self) -> Result<(Command, String, bool), Error> {
3031+
fn get_ar(&self) -> Result<(Command, PathBuf, bool), Error> {
30303032
self.try_get_archiver_and_flags()
30313033
}
30323034

@@ -3059,7 +3061,7 @@ impl Build {
30593061
Ok(self.try_get_archiver_and_flags()?.0)
30603062
}
30613063

3062-
fn try_get_archiver_and_flags(&self) -> Result<(Command, String, bool), Error> {
3064+
fn try_get_archiver_and_flags(&self) -> Result<(Command, PathBuf, bool), Error> {
30633065
let (mut cmd, name) = self.get_base_archiver()?;
30643066
let mut any_flags = false;
30653067
if let Ok(flags) = self.envflags("ARFLAGS") {
@@ -3073,12 +3075,14 @@ impl Build {
30733075
Ok((cmd, name, any_flags))
30743076
}
30753077

3076-
fn get_base_archiver(&self) -> Result<(Command, String), Error> {
3078+
fn get_base_archiver(&self) -> Result<(Command, PathBuf), Error> {
30773079
if let Some(ref a) = self.archiver {
3078-
return Ok((self.cmd(&**a), a.to_string_lossy().into_owned()));
3080+
let archiver = &**a;
3081+
return Ok((self.cmd(archiver), archiver.into()));
30793082
}
30803083

30813084
self.get_base_archiver_variant("AR", "ar")
3085+
.map(|(cmd, archiver)| (cmd, archiver.into()))
30823086
}
30833087

30843088
/// Get the ranlib that's in use for this configuration.

src/tool.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ impl Tool {
8181

8282
let stdout = match run_output(
8383
&mut cmd,
84-
&path.to_string_lossy(),
84+
path,
8585
// tool detection issues should always be shown as warnings
8686
cargo_output,
8787
)

0 commit comments

Comments
 (0)