Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 21 additions & 11 deletions compiler/rustc_codegen_llvm/src/back/command_line_args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,41 @@ mod tests;
/// The result is intended to be informational, for embedding in debug metadata,
/// and might not be properly quoted/escaped for actual command-line use.
pub(crate) fn quote_command_line_args(args: &[String]) -> String {
// Start with a decent-sized buffer, since rustc invocations tend to be long.
let mut buf = String::with_capacity(128);
// The characters we care about quoting are all ASCII, so we can get some free
// performance by performing the quoting step on bytes instead of characters.
//
// Non-ASCII bytes will be copied as-is, so the result is still UTF-8.

// Calculate an adequate buffer size, assuming no escaping will be needed.
// The `+ 3` represents an extra space and pair of quotes per arg.
let capacity_estimate = args.iter().map(|arg| arg.len() + 3).sum::<usize>();
let mut buf = Vec::with_capacity(capacity_estimate);

for arg in args {
if !buf.is_empty() {
buf.push(' ');
buf.push(b' ');
}

print_arg_quoted(&mut buf, arg);
}

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

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

buf.push('"');
for ch in arg.chars() {
if matches!(ch, '"' | '\\' | '$') {
buf.push('\\');
buf.push(b'"');
for &byte in arg.as_bytes() {
if matches!(byte, b'"' | b'\\' | b'$') {
buf.push(b'\\');
}
buf.push(ch);
buf.push(byte);
}
buf.push('"');
buf.push(b'"');
}
Loading