Skip to content

Commit 5e2a1ed

Browse files
authored
Merge pull request #201 from rust-secure-code/more-lenient-rustc-args
More lenient parsing of rustc arguments
2 parents f09d25e + 9223028 commit 5e2a1ed

File tree

2 files changed

+91
-67
lines changed

2 files changed

+91
-67
lines changed

cargo-auditable/src/rustc_arguments.rs

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ use std::{ffi::OsString, path::PathBuf};
1414
/// Includes only the rustc arguments we care about
1515
#[derive(Debug)]
1616
pub struct RustcArgs {
17-
pub crate_name: String,
17+
pub crate_name: Option<String>,
1818
pub crate_types: Vec<String>,
1919
pub cfg: Vec<String>,
2020
pub emit: Vec<String>,
21-
pub out_dir: PathBuf,
21+
pub out_dir: Option<PathBuf>,
2222
pub target: Option<String>,
2323
pub print: Vec<String>,
2424
}
@@ -52,12 +52,12 @@ impl RustcArgs {
5252
}
5353

5454
Ok(RustcArgs {
55-
crate_name: parser.value_from_str("--crate-name")?,
55+
crate_name: parser.opt_value_from_str("--crate-name")?,
5656
crate_types: parser.values_from_str("--crate-type")?,
5757
cfg: parser.values_from_str("--cfg")?,
5858
emit,
5959
out_dir: parser
60-
.value_from_os_str::<&str, PathBuf, pico_args::Error>("--out-dir", |s| {
60+
.opt_value_from_os_str::<&str, PathBuf, pico_args::Error>("--out-dir", |s| {
6161
Ok(PathBuf::from(s))
6262
})?,
6363
target: parser.opt_value_from_str("--target")?,
@@ -98,6 +98,22 @@ pub fn should_embed_audit_data(args: &RustcArgs) -> bool {
9898
mod tests {
9999
use super::*;
100100

101+
#[test]
102+
fn rustc_vv() {
103+
let raw_rustc_args = vec!["-vV"];
104+
let raw_rustc_args: Vec<OsString> = raw_rustc_args.into_iter().map(|s| s.into()).collect();
105+
let args = RustcArgs::from_vec(raw_rustc_args).unwrap();
106+
assert!(!should_embed_audit_data(&args));
107+
}
108+
109+
#[test]
110+
fn rustc_version_verbose() {
111+
let raw_rustc_args = vec!["--version", "--verbose"];
112+
let raw_rustc_args: Vec<OsString> = raw_rustc_args.into_iter().map(|s| s.into()).collect();
113+
let args = RustcArgs::from_vec(raw_rustc_args).unwrap();
114+
assert!(!should_embed_audit_data(&args));
115+
}
116+
101117
#[test]
102118
fn cargo_c_compatibility() {
103119
let raw_rustc_args = vec!["--crate-name", "rustls", "--edition=2021", "src/lib.rs", "--error-format=json", "--json=diagnostic-rendered-ansi,artifacts,future-incompat", "--crate-type", "staticlib", "--crate-type", "cdylib", "--emit=dep-info,link", "-C", "embed-bitcode=no", "-C", "debuginfo=2", "-C", "link-arg=-Wl,-soname,librustls.so.0.14.0", "-Cmetadata=rustls-ffi", "--cfg", "cargo_c", "--print", "native-static-libs", "--cfg", "feature=\"aws-lc-rs\"", "--cfg", "feature=\"capi\"", "--cfg", "feature=\"default\"", "--check-cfg", "cfg(docsrs)", "--check-cfg", "cfg(feature, values(\"aws-lc-rs\", \"capi\", \"cert_compression\", \"default\", \"no_log_capture\", \"read_buf\", \"ring\"))", "-C", "metadata=b6a43041f637feb8", "--out-dir", "/home/user/Code/rustls-ffi/target/x86_64-unknown-linux-gnu/debug/deps", "--target", "x86_64-unknown-linux-gnu", "-C", "linker=clang", "-C", "incremental=/home/user/Code/rustls-ffi/target/x86_64-unknown-linux-gnu/debug/incremental", "-L", "dependency=/home/user/Code/rustls-ffi/target/x86_64-unknown-linux-gnu/debug/deps", "-L", "dependency=/home/user/Code/rustls-ffi/target/debug/deps", "--extern", "libc=/home/user/Code/rustls-ffi/target/x86_64-unknown-linux-gnu/debug/deps/liblibc-4fc7c9f82dda33ee.rlib", "--extern", "log=/home/user/Code/rustls-ffi/target/x86_64-unknown-linux-gnu/debug/deps/liblog-6f7c8f4d1d5ec422.rlib", "--extern", "rustls=/home/user/Code/rustls-ffi/target/x86_64-unknown-linux-gnu/debug/deps/librustls-a93cda0ba0380929.rlib", "--extern", "pki_types=/home/user/Code/rustls-ffi/target/x86_64-unknown-linux-gnu/debug/deps/librustls_pki_types-27749859644f0979.rlib", "--extern", "rustls_platform_verifier=/home/user/Code/rustls-ffi/target/x86_64-unknown-linux-gnu/debug/deps/librustls_platform_verifier-bceca5cf09f3d7ba.rlib", "--extern", "webpki=/home/user/Code/rustls-ffi/target/x86_64-unknown-linux-gnu/debug/deps/libwebpki-bc4a16dd84e0b062.rlib", "-C", "link-arg=-fuse-ld=/home/user/mold-2.32.0-x86_64-linux/bin/mold", "-L", "native=/home/user/Code/rustls-ffi/target/x86_64-unknown-linux-gnu/debug/build/aws-lc-sys-d52f8990d9ede41d/out"];
@@ -106,6 +122,29 @@ mod tests {
106122
assert!(should_embed_audit_data(&args));
107123
}
108124

125+
#[test]
126+
fn embed_licensing_compatibility() {
127+
// https://github.com/rust-secure-code/cargo-auditable/issues/198
128+
let raw_rustc_args = vec![
129+
"-",
130+
"--crate-name ___",
131+
"--print=file-names",
132+
"--crate-type bin",
133+
"--crate-type rlib",
134+
"--crate-type dylib",
135+
"--crate-type cdylib",
136+
"--crate-type staticlib",
137+
"--crate-type proc-macro",
138+
"--print=sysroot",
139+
"--print=split-debuginfo",
140+
"--print=crate-name",
141+
"--print=cfg",
142+
];
143+
let raw_rustc_args: Vec<OsString> = raw_rustc_args.into_iter().map(|s| s.into()).collect();
144+
let args = RustcArgs::from_vec(raw_rustc_args).unwrap();
145+
assert!(!should_embed_audit_data(&args));
146+
}
147+
109148
#[test]
110149
fn multiple_emit_values() {
111150
let raw_rustc_args = vec![

cargo-auditable/src/rustc_wrapper.rs

Lines changed: 48 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -19,74 +19,59 @@ pub fn main(rustc_path: &OsStr) {
1919
// Binaries and C dynamic libraries are not built as non-primary packages,
2020
// so this should not cause issues with Cargo caches.
2121
if env::var_os("CARGO_PRIMARY_PACKAGE").is_some() {
22-
let arg_parsing_result = rustc_arguments::parse_args();
23-
if let Ok(args) = rustc_arguments::parse_args() {
24-
if should_embed_audit_data(&args) {
25-
// Get the audit data to embed
26-
let target_triple = args
27-
.target
28-
.clone()
29-
.unwrap_or_else(|| rustc_host_target_triple(rustc_path));
30-
let contents: Vec<u8> =
31-
collect_audit_data::compressed_dependency_list(&args, &target_triple);
32-
// write the audit info to an object file
33-
let target_info = target_info::rustc_target_info(rustc_path, &target_triple);
34-
let binfile = binary_file::create_binary_file(
35-
&target_info,
36-
&target_triple,
37-
&contents,
38-
"AUDITABLE_VERSION_INFO",
22+
let args = rustc_arguments::parse_args().unwrap(); // descriptive enough message
23+
if should_embed_audit_data(&args) {
24+
// Get the audit data to embed
25+
let target_triple = args
26+
.target
27+
.clone()
28+
.unwrap_or_else(|| rustc_host_target_triple(rustc_path));
29+
let contents: Vec<u8> =
30+
collect_audit_data::compressed_dependency_list(&args, &target_triple);
31+
// write the audit info to an object file
32+
let target_info = target_info::rustc_target_info(rustc_path, &target_triple);
33+
let binfile = binary_file::create_binary_file(
34+
&target_info,
35+
&target_triple,
36+
&contents,
37+
"AUDITABLE_VERSION_INFO",
38+
);
39+
if let Some(file) = binfile {
40+
// Place the audit data in the output dir.
41+
// We can place it anywhere really, the only concern is clutter and name collisions,
42+
// and the target dir is locked so we're probably good
43+
let filename = format!(
44+
"{}_audit_data.o",
45+
args.crate_name
46+
.expect("rustc command is missing --crate-name")
3947
);
40-
if let Some(file) = binfile {
41-
// Place the audit data in the output dir.
42-
// We can place it anywhere really, the only concern is clutter and name collisions,
43-
// and the target dir is locked so we're probably good
44-
let filename = format!("{}_audit_data.o", args.crate_name);
45-
let path = args.out_dir.join(filename);
46-
std::fs::write(&path, file).expect("Unable to write output file");
48+
let path = args
49+
.out_dir
50+
.expect("rustc command is missing --out-dir")
51+
.join(filename);
52+
std::fs::write(&path, file).expect("Unable to write output file");
4753

48-
// Modify the rustc command to link the object file with audit data
49-
let mut linker_command = OsString::from("-Clink-arg=");
50-
linker_command.push(&path);
51-
command.arg(linker_command);
52-
// Prevent the symbol from being removed as unused by the linker
53-
if is_apple(&target_info) {
54-
command.arg("-Clink-arg=-Wl,-u,_AUDITABLE_VERSION_INFO");
55-
} else if is_msvc(&target_info) {
56-
command.arg("-Clink-arg=/INCLUDE:AUDITABLE_VERSION_INFO");
57-
} else if is_wasm(&target_info) {
58-
// We don't emit the symbol name in WASM, so nothing to do
59-
} else {
60-
command.arg("-Clink-arg=-Wl,--undefined=AUDITABLE_VERSION_INFO");
61-
}
54+
// Modify the rustc command to link the object file with audit data
55+
let mut linker_command = OsString::from("-Clink-arg=");
56+
linker_command.push(&path);
57+
command.arg(linker_command);
58+
// Prevent the symbol from being removed as unused by the linker
59+
if is_apple(&target_info) {
60+
command.arg("-Clink-arg=-Wl,-u,_AUDITABLE_VERSION_INFO");
61+
} else if is_msvc(&target_info) {
62+
command.arg("-Clink-arg=/INCLUDE:AUDITABLE_VERSION_INFO");
63+
} else if is_wasm(&target_info) {
64+
// We don't emit the symbol name in WASM, so nothing to do
6265
} else {
63-
// create_binary_file() returned None, indicating an unsupported architecture
64-
eprintln!("WARNING: target '{target_triple}' is not supported by 'cargo auditable'!\n\
65-
The build will continue, but no audit data will be injected into the binary.");
66+
command.arg("-Clink-arg=-Wl,--undefined=AUDITABLE_VERSION_INFO");
6667
}
68+
} else {
69+
// create_binary_file() returned None, indicating an unsupported architecture
70+
eprintln!(
71+
"WARNING: target '{target_triple}' is not supported by 'cargo auditable'!\n\
72+
The build will continue, but no audit data will be injected into the binary."
73+
);
6774
}
68-
} else {
69-
// Failed to parse rustc arguments.
70-
71-
// This may be due to a `rustc -vV` call, or similar non-compilation command.
72-
// This never happens with Cargo - it does call `rustc -vV`,
73-
// but either bypasses the wrapper or doesn't set CARGO_PRIMARY_PACKAGE=true.
74-
// However it does happen with `sccache`:
75-
// https://github.com/rust-secure-code/cargo-auditable/issues/87
76-
// This is probably a bug in `sccache`, but it's easier to fix here.
77-
78-
// There are many non-compilation flags (and they can be compound),
79-
// so parsing them properly adds a lot of complexity.
80-
// So we just check if `--crate-name` is passed and if not,
81-
// assume that it's a non-compilation command.
82-
if env::args_os()
83-
.skip(2)
84-
.any(|arg| arg == OsStr::new("--crate-name"))
85-
{
86-
// this was a compilation command, bail
87-
arg_parsing_result.unwrap();
88-
}
89-
// for commands like `rustc --version` we just pass on the arguments without changes
9075
}
9176
}
9277

0 commit comments

Comments
 (0)