Skip to content

Commit a2d7a82

Browse files
authored
Merge pull request #177 from rust-secure-code/fix-cargo-c
Fix cargo-c
2 parents ceb4475 + c9e926f commit a2d7a82

File tree

3 files changed

+96
-20
lines changed

3 files changed

+96
-20
lines changed

cargo-auditable/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ auditable-serde = {version = "0.8.0", path = "../auditable-serde"}
1818
miniz_oxide = {version = "0.8.0"}
1919
serde_json = "1.0.57"
2020
cargo_metadata = "0.18"
21-
pico-args = "0.5"
21+
pico-args = { version = "0.5", features = ["eq-separator"] }
2222
serde = "1.0.147"
2323
wasm-gen = "0.1.4"
2424

cargo-auditable/src/rustc_arguments.rs

+92-12
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@ use std::{ffi::OsString, path::PathBuf};
1212
// https://github.com/rust-lang/rust/blob/26ecd44160f54395b3bd5558cc5352f49cb0a0ba/compiler/rustc_session/src/config.rs
1313

1414
/// Includes only the rustc arguments we care about
15+
#[derive(Debug)]
1516
pub struct RustcArgs {
1617
pub crate_name: String,
1718
pub crate_types: Vec<String>,
1819
pub cfg: Vec<String>,
20+
pub emit: Vec<String>,
1921
pub out_dir: PathBuf,
2022
pub target: Option<String>,
2123
pub print: Vec<String>,
@@ -35,18 +37,96 @@ impl RustcArgs {
3537
}
3638
}
3739

40+
impl RustcArgs {
41+
// Split into its own function for unit testing
42+
fn from_vec(raw_args: Vec<OsString>) -> Result<RustcArgs, pico_args::Error> {
43+
let mut parser = pico_args::Arguments::from_vec(raw_args);
44+
45+
// --emit requires slightly more complex parsing
46+
let raw_emit_args: Vec<String> = parser.values_from_str("--emit")?;
47+
let mut emit: Vec<String> = Vec::new();
48+
for raw_arg in raw_emit_args {
49+
for item in raw_arg.split(',') {
50+
emit.push(item.to_owned());
51+
}
52+
}
53+
54+
Ok(RustcArgs {
55+
crate_name: parser.value_from_str("--crate-name")?,
56+
crate_types: parser.values_from_str("--crate-type")?,
57+
cfg: parser.values_from_str("--cfg")?,
58+
emit,
59+
out_dir: parser
60+
.value_from_os_str::<&str, PathBuf, pico_args::Error>("--out-dir", |s| {
61+
Ok(PathBuf::from(s))
62+
})?,
63+
target: parser.opt_value_from_str("--target")?,
64+
print: parser.values_from_str("--print")?,
65+
})
66+
}
67+
}
68+
3869
pub fn parse_args() -> Result<RustcArgs, pico_args::Error> {
3970
let raw_args: Vec<OsString> = std::env::args_os().skip(2).collect();
40-
let mut parser = pico_args::Arguments::from_vec(raw_args);
41-
42-
Ok(RustcArgs {
43-
crate_name: parser.value_from_str("--crate-name")?,
44-
crate_types: parser.values_from_str("--crate-type")?,
45-
cfg: parser.values_from_str("--cfg")?,
46-
out_dir: parser.value_from_os_str::<&str, PathBuf, pico_args::Error>("--out-dir", |s| {
47-
Ok(PathBuf::from(s))
48-
})?,
49-
target: parser.opt_value_from_str("--target")?,
50-
print: parser.values_from_str("--print")?,
51-
})
71+
RustcArgs::from_vec(raw_args)
72+
}
73+
74+
pub fn should_embed_audit_data(args: &RustcArgs) -> bool {
75+
// Only inject audit data into crate types 'bin' and 'cdylib',
76+
// it doesn't make sense for static libs and weird other types.
77+
if !(args.crate_types.contains(&"bin".to_owned())
78+
|| args.crate_types.contains(&"cdylib".to_owned()))
79+
{
80+
return false;
81+
}
82+
83+
// when --emit is specified explicitly, only inject audit data for --emit=link
84+
// because it doesn't make sense for all other types such as llvm-ir, asm, etc.
85+
if !args.emit.is_empty() && !args.emit.contains(&"link".to_owned()) {
86+
return false;
87+
}
88+
89+
// --print disables compilation UNLESS --emit is also specified
90+
if !args.print.is_empty() && args.emit.is_empty() {
91+
return false;
92+
}
93+
94+
true
95+
}
96+
97+
#[cfg(test)]
98+
mod tests {
99+
use super::*;
100+
101+
#[test]
102+
fn cargo_c_compatibility() {
103+
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"];
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 multiple_emit_values() {
111+
let raw_rustc_args = vec![
112+
"--emit=dep-info,link",
113+
"--emit",
114+
"llvm-bc",
115+
// end of interesting args, start of boilerplate
116+
"--crate-name",
117+
"foobar",
118+
"--out-dir",
119+
"/foo/bar",
120+
];
121+
let raw_rustc_args: Vec<OsString> = raw_rustc_args.into_iter().map(|s| s.into()).collect();
122+
let mut args = RustcArgs::from_vec(raw_rustc_args).unwrap();
123+
124+
let expected = vec!["dep-info", "link", "llvm-bc"];
125+
let mut expected: Vec<String> = expected.into_iter().map(|s| s.into()).collect();
126+
127+
args.emit.sort();
128+
expected.sort();
129+
130+
assert_eq!(args.emit, expected)
131+
}
52132
}

cargo-auditable/src/rustc_wrapper.rs

+3-7
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ use std::{
77
use crate::{
88
binary_file, collect_audit_data,
99
platform_detection::{is_apple, is_msvc, is_wasm},
10-
rustc_arguments, target_info,
10+
rustc_arguments::{self, should_embed_audit_data},
11+
target_info,
1112
};
1213

1314
use std::io::BufRead;
@@ -20,12 +21,7 @@ pub fn main(rustc_path: &OsStr) {
2021
if env::var_os("CARGO_PRIMARY_PACKAGE").is_some() {
2122
let arg_parsing_result = rustc_arguments::parse_args();
2223
if let Ok(args) = rustc_arguments::parse_args() {
23-
// Only inject audit data into crate types 'bin' and 'cdylib',
24-
// and only if --print is not specified (which disables compilation)
25-
if args.print.is_empty()
26-
&& (args.crate_types.contains(&"bin".to_owned())
27-
|| args.crate_types.contains(&"cdylib".to_owned()))
28-
{
24+
if should_embed_audit_data(&args) {
2925
// Get the audit data to embed
3026
let target_triple = args
3127
.target

0 commit comments

Comments
 (0)