Separate symcc crate (#244)

* create a separate crate for symcc url and commit hash

also contains functions to checkout and build symcc from a build script

* fix dockerfile

* clippy
This commit is contained in:
julihoh 2021-08-05 21:57:39 +02:00 committed by GitHub
parent 16c3a07be7
commit 1dddf7e677
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 111 additions and 75 deletions

View File

@ -15,6 +15,7 @@ members = [
"libafl_sugar",
"libafl_tests",
"libafl_concolic/symcc_runtime",
"libafl_concolic/symcc_libafl",
"libafl_concolic/test/dump_constraints",
"libafl_concolic/test/runtime_test",
]

View File

@ -65,6 +65,9 @@ COPY scripts/dummy.rs libafl_concolic/test/runtime_test/src/lib.rs
COPY libafl_concolic/symcc_runtime/Cargo.toml libafl_concolic/symcc_runtime/build.rs libafl_concolic/symcc_runtime/
COPY scripts/dummy.rs libafl_concolic/symcc_runtime/src/lib.rs
COPY libafl_concolic/symcc_libafl/Cargo.toml libafl_concolic/symcc_libafl/
COPY scripts/dummy.rs libafl_concolic/symcc_libafl/src/lib.rs
RUN cargo build && cargo build --release
COPY scripts scripts
@ -94,6 +97,7 @@ COPY libafl_frida/src libafl_frida/src
RUN touch libafl_qemu/src/lib.rs
COPY libafl_qemu/src libafl_qemu/src
RUN touch libafl_frida/src/lib.rs
COPY libafl_concolic/symcc_libafl libafl_concolic/symcc_libafl
RUN cargo build && cargo build --release
# Copy fuzzers over

View File

@ -24,3 +24,4 @@ cc = { version = "1.0", features = ["parallel"] }
num_cpus = "1.0"
cmake = "0.1"
which = "4.1"
symcc_libafl = {path = "../../../libafl_concolic/symcc_libafl"}

View File

@ -92,48 +92,11 @@ fn main() {
println!("cargo:rerun-if-changed=harness_symcc.c");
}
const SYMCC_REPO_URL: &str = "https://github.com/AFLplusplus/symcc.git";
const SYMCC_REPO_COMMIT: &str = "45cde0269ae22aef4cca2e1fb98c3b24f7bb2984";
fn clone_and_build_symcc(out_path: &Path) -> PathBuf {
let repo_dir = out_path.join("libafl_symcc_src");
if !repo_dir.exists() {
build_dep_check(&["git"]);
let mut cmd = Command::new("git");
cmd.arg("clone").arg(SYMCC_REPO_URL).arg(&repo_dir);
let output = cmd.output().expect("failed to execute git clone");
if output.status.success() {
let mut cmd = Command::new("git");
cmd.arg("checkout")
.arg(SYMCC_REPO_COMMIT)
.current_dir(&repo_dir);
let output = cmd.output().expect("failed to execute git checkout");
if output.status.success() {
} else {
println!("failed to checkout symcc git repository commit:");
let mut stdout = stdout();
stdout
.write_all(&output.stderr)
.expect("failed to write git error message to stdout");
exit(1)
}
} else {
println!("failed to clone symcc git repository:");
let mut stdout = stdout();
stdout
.write_all(&output.stderr)
.expect("failed to write git error message to stdout");
exit(1)
}
symcc_libafl::clone_symcc(&repo_dir);
}
build_dep_check(&["cmake"]);
use cmake::Config;
Config::new(repo_dir)
.define("Z3_TRUST_SYSTEM_VERSION", "ON")
.no_build_target(true)
.build()
.join("build")
symcc_libafl::build_symcc(&repo_dir)
}

View File

@ -0,0 +1,15 @@
[package]
name = "symcc_libafl"
version = "0.1.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]
default = ["build", "clone"]
build = ["which", "cmake"] # common functionality to build symcc
clone = ["which"] # common functionality to check out the symcc repo using git
[dependencies]
which = { version = "4.1", optional = true }
cmake = { version = "0.1", optional = true }

View File

@ -0,0 +1,81 @@
//! This is a 'meta-package' for libafl that exposes a consistent URL and commit hash for the
//! [`SymCC` fork](https://github.com/AFLplusplus/symcc).
/// The URL of the `LibAFL` `SymCC` fork.
pub const SYMCC_REPO_URL: &str = "https://github.com/AFLplusplus/symcc.git";
/// The commit of the `LibAFL` `SymCC` fork.
pub const SYMCC_REPO_COMMIT: &str = "45cde0269ae22aef4cca2e1fb98c3b24f7bb2984";
#[cfg(feature = "clone")]
mod clone {
use std::{
io::{stdout, Write},
path::Path,
process::Command,
};
use which::which;
use crate::{SYMCC_REPO_COMMIT, SYMCC_REPO_URL};
/// Checks out the repository into the given directory with the given URL and commit hash.
/// Any errors will trigger a panic.
pub fn clone_symcc_at_version(path: &Path, url: &str, commit: &str) {
if which("git").is_err() {
panic!("ERROR: unable to find git. Git is required to download SymCC.");
}
let mut cmd = Command::new("git");
cmd.arg("clone").arg(url).arg(&path);
let output = cmd.output().expect("failed to execute git clone");
if output.status.success() {
let mut cmd = Command::new("git");
cmd.arg("checkout").arg(commit).current_dir(&path);
let output = cmd.output().expect("failed to execute git checkout");
if !output.status.success() {
println!("failed to checkout symcc git repository commit:");
let mut stdout = stdout();
stdout
.write_all(&output.stderr)
.expect("failed to write git error message to stdout");
panic!();
}
} else {
println!("failed to clone symcc git repository:");
let mut stdout = stdout();
stdout
.write_all(&output.stderr)
.expect("failed to write git error message to stdout");
panic!();
}
}
/// Checks out the repository into the given directory.
/// Any errors will trigger a panic.
pub fn clone_symcc(path: &Path) {
clone_symcc_at_version(path, SYMCC_REPO_URL, SYMCC_REPO_COMMIT);
}
}
#[cfg(feature = "clone")]
pub use clone::clone_symcc;
#[cfg(feature = "build")]
mod build {
use std::path::{Path, PathBuf};
/// Builds `SymCC` at the given directory using [`cmake`](https://crates.io/crates/cmake).
/// Returns the build artifact directory.
#[must_use]
pub fn build_symcc(path: &Path) -> PathBuf {
use cmake::Config;
Config::new(path)
.define("Z3_TRUST_SYSTEM_VERSION", "ON")
.no_build_target(true)
.build()
.join("build")
}
}
#[cfg(feature = "build")]
pub use build::build_symcc;

View File

@ -22,3 +22,4 @@ bindgen = "0.58"
regex = "1"
lazy_static = "1.4"
which = "4.1"
symcc_libafl = {path = "../symcc_libafl"}

View File

@ -1,16 +1,14 @@
use std::{
env,
fs::File,
io::{stdout, Write},
io::Write,
path::{Path, PathBuf},
process::{exit, Command},
process::exit,
};
use lazy_static::lazy_static;
use regex::{Regex, RegexBuilder};
const SYMCC_REPO_URL: &str = "https://github.com/AFLplusplus/symcc.git";
const SYMCC_REPO_COMMIT: &str = "45cde0269ae22aef4cca2e1fb98c3b24f7bb2984";
use symcc_libafl::clone_symcc;
const SYMCC_RUNTIME_FUNCTION_NAME_PREFIX: &str = "_cpp_";
@ -108,38 +106,10 @@ fn write_cpp_function_export_macro(out_path: &Path, cpp_bindings: &bindgen::Bind
fn checkout_symcc(out_path: &Path) -> PathBuf {
let repo_dir = out_path.join("libafl_symcc_src");
if repo_dir.exists() {
if !repo_dir.exists() {
clone_symcc(&repo_dir);
}
repo_dir
} else {
build_dep_check(&["git"]);
let mut cmd = Command::new("git");
cmd.arg("clone").arg(SYMCC_REPO_URL).arg(&repo_dir);
let output = cmd.output().expect("failed to execute git clone");
if output.status.success() {
let mut cmd = Command::new("git");
cmd.arg("checkout")
.arg(SYMCC_REPO_COMMIT)
.current_dir(&repo_dir);
let output = cmd.output().expect("failed to execute git checkout");
if output.status.success() {
repo_dir
} else {
println!("failed to checkout symcc git repository commit:");
let mut stdout = stdout();
stdout
.write_all(&output.stderr)
.expect("failed to write git error message to stdout");
exit(1)
}
} else {
println!("failed to clone symcc git repository:");
let mut stdout = stdout();
stdout
.write_all(&output.stderr)
.expect("failed to write git error message to stdout");
exit(1)
}
}
}
fn write_rust_runtime_macro_file(out_path: &Path, symcc_src_path: &Path) {