Skip to content

Commit

Permalink
[casr-afl][casr-libfuzzer] Add hints (#230)
Browse files Browse the repository at this point in the history
  • Loading branch information
hkctkuy authored Nov 28, 2024
1 parent 4be568a commit af9e9e4
Show file tree
Hide file tree
Showing 10 changed files with 62 additions and 23 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/coverage.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
- name: Build and Run Tests
env:
CARGO_INCREMENTAL: 0
RUSTFLAGS: '-Cinstrument-coverage -Zprofile -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort'
RUSTFLAGS: '-Cinstrument-coverage -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort'
RUSTDOCFLAGS: '-Cpanic=abort'
LLVM_PROFILE_FILE: 'casr-%p-%m.profraw'
run: |
Expand All @@ -61,6 +61,6 @@ jobs:
--excl-stop '^}$' \
-t lcov
- name: Upload Coverage Reports to Codecov
uses: codecov/codecov-action@v3
uses: codecov/codecov-action@v5
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
3 changes: 2 additions & 1 deletion .github/workflows/riscv64.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ jobs:
install: |
export CARGO_TERM_COLOR=always
export CARGO_REGISTRIES_CRATES_IO_PROTOCOL=sparse
apt-get update && apt-get install -y gdb pip curl python3.10-dev clang llvm build-essential
apt-get update \
&& apt-get install -y gdb pip curl python3-dev clang llvm build-essential
curl https://sh.rustup.rs -o rustup.sh && chmod +x rustup.sh && \
./rustup.sh -y && rm rustup.sh
run: |
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[![Crates.io](https://img.shields.io/crates/v/casr)](https://crates.io/crates/casr)
[![Documentation](https://docs.rs/libcasr/badge.svg)](https://docs.rs/libcasr)
[![codecov](https://codecov.io/github/ispras/casr/graph/badge.svg?token=D9VY1WRWA7)](https://codecov.io/github/ispras/casr)
[![codecov](https://codecov.io/github/ispras/casr/graph/badge.svg?token=D9VY1WRWA7)](https://app.codecov.io/github/ispras/casr)
[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://github.com/ispras/casr/blob/master/LICENSE)

[![amd64](https://github.com/ispras/casr/actions/workflows/amd64.yml/badge.svg?branch=master)](https://github.com/ispras/casr/actions/workflows/amd64.yml)
Expand Down
21 changes: 17 additions & 4 deletions casr/src/bin/casr-afl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,15 @@ fn main() -> Result<()> {
.long("no-cluster")
.help("Do not cluster CASR reports")
)
.arg(
Arg::new("hint")
.long("hint")
.value_name("HINT")
.action(ArgAction::Set)
.default_value("auto")
.value_parser(["auto", "gdb", "san", "csharp"])
.help("Hint to force run casr-HINT tool to analyze crashes")
)
.arg(
Arg::new("ARGS")
.action(ArgAction::Set)
Expand All @@ -129,6 +138,8 @@ fn main() -> Result<()> {
bail!("ARGS is empty, but \"ignore-cmdline\" option is provided.");
}

let hint = matches.get_one::<String>("hint").unwrap();

// Get all crashes.
let mut crashes: HashMap<String, CrashInfo> = HashMap::new();
for node_dir in fs::read_dir(matches.get_one::<PathBuf>("input").unwrap())? {
Expand All @@ -152,9 +163,11 @@ fn main() -> Result<()> {
continue;
}
};
crash_info.casr_tool = if !crash_info.target_args.is_empty()
&& (crash_info.target_args[0].ends_with("dotnet")
|| crash_info.target_args[0].ends_with("mono"))
crash_info.casr_tool = if hint == "csharp"
|| hint == "auto"
&& !crash_info.target_args.is_empty()
&& (crash_info.target_args[0].ends_with("dotnet")
|| crash_info.target_args[0].ends_with("mono"))
{
is_casr_gdb = false;
util::get_path("casr-csharp")?
Expand All @@ -169,7 +182,7 @@ fn main() -> Result<()> {
.map(|x| x + 1);

// When we triage crashes for binaries, use casr-san.
if is_casr_gdb {
if hint == "san" || hint == "auto" && is_casr_gdb {
if let Some(target) = crash_info.target_args.first() {
match util::symbols_list(Path::new(target)) {
Ok(list) => {
Expand Down
2 changes: 1 addition & 1 deletion casr/src/bin/casr-cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ fn main() -> Result<()> {
));

if !report.package.is_empty() && !report.package_version.is_empty() {
header_string.append(&format!(
header_string.append(format!(
" from {} {}",
report.package, report.package_version
));
Expand Down
32 changes: 25 additions & 7 deletions casr/src/bin/casr-libfuzzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,15 @@ fn main() -> Result<()> {
.action(ArgAction::Set)
.help("Add \"--casr-gdb-args \'./gdb_fuzz_target <arguments>\'\" to generate additional crash reports with casr-gdb (e.g., test whether program crashes without sanitizers)"),
)
.arg(
Arg::new("hint")
.long("hint")
.value_name("HINT")
.action(ArgAction::Set)
.default_value("auto")
.value_parser(["auto", "gdb", "java", "js", "python", "san"])
.help("Hint to force run casr-HINT tool to analyze crashes")
)
.arg(
Arg::new("ARGS")
.action(ArgAction::Set)
Expand Down Expand Up @@ -132,22 +141,31 @@ fn main() -> Result<()> {
Vec::new()
};

// Get hint
let hint = matches.get_one::<String>("hint").unwrap();

// Get tool.
let mut envs = HashMap::new();
let tool = if argv[0].ends_with(".py") {
let tool = if hint == "python" || hint == "auto" && argv[0].ends_with(".py") {
envs.insert("LD_PRELOAD".to_string(), util::get_atheris_lib()?);
"casr-python"
} else if argv[0].ends_with("jazzer") || argv[0].ends_with("java") {
} else if hint == "java"
|| hint == "auto" && (argv[0].ends_with("jazzer") || argv[0].ends_with("java"))
{
"casr-java"
} else if argv[0].ends_with(".js")
|| argv[0].ends_with("node")
|| argv.len() > 1 && argv[0].ends_with("npx") && argv[1] == "jazzer"
|| argv[0].ends_with("jsfuzz")
} else if hint == "js"
|| hint == "auto"
&& (argv[0].ends_with(".js")
|| argv[0].ends_with("node")
|| argv.len() > 1 && argv[0].ends_with("npx") && argv[1] == "jazzer"
|| argv[0].ends_with("jsfuzz"))
{
"casr-js"
} else {
let sym_list = util::symbols_list(Path::new(argv[0]))?;
if sym_list.contains("__asan") || sym_list.contains("runtime.go") {
if hint == "san"
|| hint == "auto" && (sym_list.contains("__asan") || sym_list.contains("runtime.go"))
{
"casr-san"
} else {
"casr-gdb"
Expand Down
2 changes: 1 addition & 1 deletion casr/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ pub fn initialize_dirs(matches: &clap::ArgMatches) -> Result<&PathBuf> {
bail!("Failed to create dir {}", &casrep_dir.to_str().unwrap());
}
} else if !output_dir.exists() && fs::create_dir_all(output_dir).is_err() {
format!("Couldn't create output directory {}", output_dir.display());
bail!("Couldn't create output directory {}", output_dir.display());
}

// Get oom dir
Expand Down
5 changes: 5 additions & 0 deletions casr/tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4683,6 +4683,7 @@ fn test_casr_python_call_san_df() {
let work_dir = abs_path("tests/casr_tests/python");
let test_dir = abs_path("tests/tmp_tests_casr/test_casr_python_call_san_df");

let _ = std::fs::remove_dir_all(&test_dir);
let _ = copy_dir(work_dir, &test_dir).unwrap();

let paths = [
Expand Down Expand Up @@ -5924,6 +5925,8 @@ fn test_casr_afl_csharp() {
];

let _ = fs::remove_dir_all(&paths[1]);
let _ = fs::remove_dir_all(&paths[4]);
let _ = fs::remove_dir_all(&paths[5]);
let _ = fs::create_dir(abs_path("tests/tmp_tests_casr"));
let _ = copy_dir(&paths[2], &paths[4]).unwrap();
let _ = copy_dir(&paths[3], &paths[5]).unwrap();
Expand Down Expand Up @@ -6024,6 +6027,8 @@ fn test_casr_afl_csharp_ignore_cmd() {
];

let _ = fs::remove_dir_all(&paths[1]);
let _ = fs::remove_dir_all(&paths[4]);
let _ = fs::remove_dir_all(&paths[5]);
let _ = fs::create_dir(abs_path("tests/tmp_tests_casr"));
let _ = copy_dir(&paths[2], &paths[4]).unwrap();
let _ = copy_dir(&paths[3], &paths[5]).unwrap();
Expand Down
6 changes: 6 additions & 0 deletions docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,9 @@ Triage crashes found by AFL++/Sharpfuzz
--ignore-cmdline Force <ARGS> usage to run target instead of searching
for cmdline files in AFL fuzzing directory
--no-cluster Do not cluster CASR reports
--hint <HINT> Hint to force run casr-HINT tool to analyze crashes
[default: auto] [possible values: auto, gdb, san,
csharp]
-h, --help Print help
-V, --version Print version

Expand Down Expand Up @@ -603,6 +606,9 @@ Triage crashes found by libFuzzer based fuzzer
Add "--casr-gdb-args './gdb_fuzz_target <arguments>'" to generate additional
crash reports with casr-gdb (e.g., test whether program crashes without
sanitizers)
--hint <HINT>
Hint to force run casr-HINT tool to analyze crashes [default: auto] [possible
values: auto, gdb, java, js, python, san]
-h, --help
Print help
-V, --version
Expand Down
8 changes: 2 additions & 6 deletions libcasr/src/cluster.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,16 +197,12 @@ impl Cluster {
/// NOTE: Result also can be interpreted as diameter of cluster merge result
pub fn dist_rep(cluster: &Cluster, report: &ReportInfo) -> f64 {
let (_, (trace, _)) = report;
if let Some(max) = cluster
cluster
.stacktraces()
.iter()
.map(|s| 1.0 - similarity(s, trace))
.max_by(|a, b| a.total_cmp(b))
{
max
} else {
0f64
}
.unwrap_or(0f64)
}
}

Expand Down

0 comments on commit af9e9e4

Please sign in to comment.