Skip to content

Commit

Permalink
Merge pull request #177 from rust-secure-code/fix-cargo-c
Browse files Browse the repository at this point in the history
Fix cargo-c
  • Loading branch information
Shnatsel authored Nov 23, 2024
2 parents ceb4475 + c9e926f commit a2d7a82
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 20 deletions.
2 changes: 1 addition & 1 deletion cargo-auditable/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ auditable-serde = {version = "0.8.0", path = "../auditable-serde"}
miniz_oxide = {version = "0.8.0"}
serde_json = "1.0.57"
cargo_metadata = "0.18"
pico-args = "0.5"
pico-args = { version = "0.5", features = ["eq-separator"] }
serde = "1.0.147"
wasm-gen = "0.1.4"

Expand Down
104 changes: 92 additions & 12 deletions cargo-auditable/src/rustc_arguments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ use std::{ffi::OsString, path::PathBuf};
// https://github.com/rust-lang/rust/blob/26ecd44160f54395b3bd5558cc5352f49cb0a0ba/compiler/rustc_session/src/config.rs

/// Includes only the rustc arguments we care about
#[derive(Debug)]
pub struct RustcArgs {
pub crate_name: String,
pub crate_types: Vec<String>,
pub cfg: Vec<String>,
pub emit: Vec<String>,
pub out_dir: PathBuf,
pub target: Option<String>,
pub print: Vec<String>,
Expand All @@ -35,18 +37,96 @@ impl RustcArgs {
}
}

impl RustcArgs {
// Split into its own function for unit testing
fn from_vec(raw_args: Vec<OsString>) -> Result<RustcArgs, pico_args::Error> {
let mut parser = pico_args::Arguments::from_vec(raw_args);

// --emit requires slightly more complex parsing
let raw_emit_args: Vec<String> = parser.values_from_str("--emit")?;
let mut emit: Vec<String> = Vec::new();
for raw_arg in raw_emit_args {
for item in raw_arg.split(',') {
emit.push(item.to_owned());
}
}

Ok(RustcArgs {
crate_name: parser.value_from_str("--crate-name")?,
crate_types: parser.values_from_str("--crate-type")?,
cfg: parser.values_from_str("--cfg")?,
emit,
out_dir: parser
.value_from_os_str::<&str, PathBuf, pico_args::Error>("--out-dir", |s| {
Ok(PathBuf::from(s))
})?,
target: parser.opt_value_from_str("--target")?,
print: parser.values_from_str("--print")?,
})
}
}

pub fn parse_args() -> Result<RustcArgs, pico_args::Error> {
let raw_args: Vec<OsString> = std::env::args_os().skip(2).collect();
let mut parser = pico_args::Arguments::from_vec(raw_args);

Ok(RustcArgs {
crate_name: parser.value_from_str("--crate-name")?,
crate_types: parser.values_from_str("--crate-type")?,
cfg: parser.values_from_str("--cfg")?,
out_dir: parser.value_from_os_str::<&str, PathBuf, pico_args::Error>("--out-dir", |s| {
Ok(PathBuf::from(s))
})?,
target: parser.opt_value_from_str("--target")?,
print: parser.values_from_str("--print")?,
})
RustcArgs::from_vec(raw_args)
}

pub fn should_embed_audit_data(args: &RustcArgs) -> bool {
// Only inject audit data into crate types 'bin' and 'cdylib',
// it doesn't make sense for static libs and weird other types.
if !(args.crate_types.contains(&"bin".to_owned())
|| args.crate_types.contains(&"cdylib".to_owned()))
{
return false;
}

// when --emit is specified explicitly, only inject audit data for --emit=link
// because it doesn't make sense for all other types such as llvm-ir, asm, etc.
if !args.emit.is_empty() && !args.emit.contains(&"link".to_owned()) {
return false;
}

// --print disables compilation UNLESS --emit is also specified
if !args.print.is_empty() && args.emit.is_empty() {
return false;
}

true
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn cargo_c_compatibility() {
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"];
let raw_rustc_args: Vec<OsString> = raw_rustc_args.into_iter().map(|s| s.into()).collect();
let args = RustcArgs::from_vec(raw_rustc_args).unwrap();
assert!(should_embed_audit_data(&args));
}

#[test]
fn multiple_emit_values() {
let raw_rustc_args = vec![
"--emit=dep-info,link",
"--emit",
"llvm-bc",
// end of interesting args, start of boilerplate
"--crate-name",
"foobar",
"--out-dir",
"/foo/bar",
];
let raw_rustc_args: Vec<OsString> = raw_rustc_args.into_iter().map(|s| s.into()).collect();
let mut args = RustcArgs::from_vec(raw_rustc_args).unwrap();

let expected = vec!["dep-info", "link", "llvm-bc"];
let mut expected: Vec<String> = expected.into_iter().map(|s| s.into()).collect();

args.emit.sort();
expected.sort();

assert_eq!(args.emit, expected)
}
}
10 changes: 3 additions & 7 deletions cargo-auditable/src/rustc_wrapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ use std::{
use crate::{
binary_file, collect_audit_data,
platform_detection::{is_apple, is_msvc, is_wasm},
rustc_arguments, target_info,
rustc_arguments::{self, should_embed_audit_data},
target_info,
};

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

0 comments on commit a2d7a82

Please sign in to comment.