diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 25bf96a1b3..5b68367319 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -105,6 +105,10 @@ jobs: - name: Run miri tests run: RUST_BACKTRACE=1 MIRIFLAGS="-Zmiri-disable-isolation" cargo +nightly miri test + # --- test embedding the libafl_libfuzzer_runtime library + - name: Test Build libafl_libfuzzer with embed + run: cargo +nightly test --features=embed-runtime --manifest-path libafl_libfuzzer/Cargo.toml + ubuntu-check: runs-on: ubuntu-22.04 steps: diff --git a/libafl_libfuzzer/Cargo.toml b/libafl_libfuzzer/Cargo.toml index ffbfe10b4f..1182d4a334 100644 --- a/libafl_libfuzzer/Cargo.toml +++ b/libafl_libfuzzer/Cargo.toml @@ -14,7 +14,7 @@ include = [ "/Cargo.toml", "/build.rs", "/libafl_libfuzzer_runtime", - "!/libafl_libfuzzer_runtime/target" + "!/libafl_libfuzzer_runtime/target", ] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -30,6 +30,10 @@ rustversion = "1.0" arbitrary-derive = ["libfuzzer-sys/arbitrary-derive"] ## Enables fuzzer introspection with LibAFL's `introspection` feature introspection = [] +## Embeds the built libafl_libfuzzer_runtime library into the crate with include_bytes! for use +## in downstream cases like libafl_cc linking the runtime with: +## `-fsanitize=fuzzer-no-link -l:libafl_libfuzzer_runtime.a` +embed-runtime = [] [dependencies] libfuzzer-sys = { version = "0.4.7", default-features = false } @@ -39,6 +43,4 @@ document-features = { version = "0.2" } features = ["document-features"] all-features = true -rustdoc-args = [ - "--cfg", "docsrs", -] +rustdoc-args = ["--cfg", "docsrs"] diff --git a/libafl_libfuzzer/build.rs b/libafl_libfuzzer/build.rs index 962488e9c9..f5797523f0 100644 --- a/libafl_libfuzzer/build.rs +++ b/libafl_libfuzzer/build.rs @@ -70,6 +70,16 @@ fn main() { let mut lib_path = custom_lib_dir.join(std::env::var_os("TARGET").unwrap()); lib_path.push("release"); + #[cfg(all(feature = "embed-runtime", target_family = "unix"))] + { + // NOTE: lib, .a are added always on unix-like systems as described in: + // https://gist.github.com/novafacing/1389cbb2f0a362d7eb103e67b4468e2b + println!( + "cargo:rustc-env=LIBAFL_LIBFUZZER_RUNTIME_PATH={}", + lib_path.join("libafl_libfuzzer_runtime.a").display() + ); + } + println!( "cargo:rustc-link-search=native={}", lib_path.to_str().unwrap() diff --git a/libafl_libfuzzer/src/lib.rs b/libafl_libfuzzer/src/lib.rs index be0df15c20..dd01be7b65 100644 --- a/libafl_libfuzzer/src/lib.rs +++ b/libafl_libfuzzer/src/lib.rs @@ -90,3 +90,28 @@ extern "C" { harness_fn: Option c_int>, ) -> c_int; } + +#[cfg(all( + feature = "embed-runtime", + target_family = "unix", + // Disable when building with clippy, as it will complain about the missing environment + // variable which is set by the build script, which is not run under clippy. + not(feature = "cargo-clippy") +))] +pub const LIBAFL_LIBFUZZER_RUNTIME_LIBRARY: &'static [u8] = + include_bytes!(env!("LIBAFL_LIBFUZZER_RUNTIME_PATH")); + +#[cfg(test)] +mod tests { + #[cfg(all(feature = "embed-runtime", not(feature = "cargo-clippy")))] + #[test] + fn test_embed_runtime_sized() { + use crate::LIBAFL_LIBFUZZER_RUNTIME_LIBRARY; + + assert_ne!( + LIBAFL_LIBFUZZER_RUNTIME_LIBRARY.len(), + 0, + "Runtime library empty" + ); + } +}