Skip to content

Commit 164c976

Browse files
committed
Perform target-machine command-line quoting as bytes, not characters
This works because the only characters we care about escaping are ASCII characters, so forwarding non-ASCII UTF-8 bytes as-is still produces correct results.
1 parent ae12bc2 commit 164c976

File tree

1 file changed

+21
-11
lines changed

1 file changed

+21
-11
lines changed

compiler/rustc_codegen_llvm/src/back/command_line_args.rs

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,31 +7,41 @@ mod tests;
77
/// The result is intended to be informational, for embedding in debug metadata,
88
/// and might not be properly quoted/escaped for actual command-line use.
99
pub(crate) fn quote_command_line_args(args: &[String]) -> String {
10-
// Start with a decent-sized buffer, since rustc invocations tend to be long.
11-
let mut buf = String::with_capacity(128);
10+
// The characters we care about quoting are all ASCII, so we can get some free
11+
// performance by performing the quoting step on bytes instead of characters.
12+
//
13+
// Non-ASCII bytes will be copied as-is, so the result is still UTF-8.
14+
15+
// Calculate an adequate buffer size, assuming no escaping will be needed.
16+
// The `+ 3` represents an extra space and pair of quotes per arg.
17+
let capacity_estimate = args.iter().map(|arg| arg.len() + 3).sum::<usize>();
18+
let mut buf = Vec::with_capacity(capacity_estimate);
1219

1320
for arg in args {
1421
if !buf.is_empty() {
15-
buf.push(' ');
22+
buf.push(b' ');
1623
}
1724

1825
print_arg_quoted(&mut buf, arg);
1926
}
2027

21-
buf
28+
// Converting back to String isn't strictly necessary, since the bytes are
29+
// only passed to LLVM which doesn't care, but validating should be cheap
30+
// and it's nice to have some assurance that we didn't mess up.
31+
String::from_utf8(buf).expect("quoted args should still be UTF-8")
2232
}
2333

2434
/// Equivalent to LLVM's `sys::printArg` with quoting always enabled
2535
/// (see llvm/lib/Support/Program.cpp).
26-
fn print_arg_quoted(buf: &mut String, arg: &str) {
36+
fn print_arg_quoted(buf: &mut Vec<u8>, arg: &str) {
2737
buf.reserve(arg.len() + 2);
2838

29-
buf.push('"');
30-
for ch in arg.chars() {
31-
if matches!(ch, '"' | '\\' | '$') {
32-
buf.push('\\');
39+
buf.push(b'"');
40+
for &byte in arg.as_bytes() {
41+
if matches!(byte, b'"' | b'\\' | b'$') {
42+
buf.push(b'\\');
3343
}
34-
buf.push(ch);
44+
buf.push(byte);
3545
}
36-
buf.push('"');
46+
buf.push(b'"');
3747
}

0 commit comments

Comments
 (0)