Skip to content

Commit

Permalink
[libcasr] Rust backtrace parsing (#146)
Browse files Browse the repository at this point in the history
* [libcasr] Rust backtrace parsing

* Add Rust backtrace parser to casr-san

* Update casr-cli and report.rs

* Update docs/usage.

* Fix comments + panic_test

* let-else

* Fix docs/usage.

* Fix comments

* Allow column to be absent
  • Loading branch information
anfedotoff authored Sep 22, 2023
1 parent e072cab commit 9ed7230
Show file tree
Hide file tree
Showing 8 changed files with 343 additions and 4 deletions.
14 changes: 14 additions & 0 deletions casr/src/bin/casr-cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,16 @@ fn build_tree_report(
tree.collapse_item(row);
}

if !report.rust_report.is_empty() {
row = tree
.insert_container_item("RustReport".to_string(), Placement::After, row)
.unwrap();
report.rust_report.iter().for_each(|e| {
tree.insert_item(e.clone(), Placement::LastChild, row);
});
tree.collapse_item(row);
}

if !report.source.is_empty() {
row = tree
.insert_container_item("Source".to_string(), Placement::After, row)
Expand Down Expand Up @@ -612,6 +622,10 @@ fn build_slider_report(
select.add_item("GoReport", report.go_report.join("\n"));
}

if !report.rust_report.is_empty() {
select.add_item("RustReport", report.rust_report.join("\n"));
}

if !report.source.is_empty() {
select.add_item("Source", report.source.join("\n"));
}
Expand Down
5 changes: 5 additions & 0 deletions casr/src/bin/casr-dojo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,11 @@ fn get_report_description(
d += &report.go_report.join("\n");
d += "\n```\n\n";
}
if !report.rust_report.is_empty() {
d += "# Rust report\n\n```\n";
d += &report.rust_report.join("\n");
d += "\n```\n\n";
}
d += "# Stack trace\n\n```\n";
d += &report.stacktrace.join("\n");
d += "\n```\n\n# Environment variables\n\n```\n";
Expand Down
12 changes: 10 additions & 2 deletions casr/src/bin/casr-san.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use libcasr::gdb::*;
use libcasr::go::*;
use libcasr::init_ignored_frames;
use libcasr::report::CrashReport;
use libcasr::rust::RustPanic;
use libcasr::rust::{RustPanic, RustStacktrace};
use libcasr::severity::Severity;
use libcasr::stacktrace::*;

Expand Down Expand Up @@ -165,9 +165,9 @@ fn main() -> Result<()> {
report.stdin = file_path.display().to_string();
}

// If it is possible to extract Go stacktrace, it is Go.
let stacktrace: Stacktrace;
if let Ok(raw_stacktrace) = GoStacktrace::extract_stacktrace(&sanitizers_stderr) {
// If it is possible to extract Go stacktrace, it is Go.
report.stacktrace = raw_stacktrace;
stacktrace = GoStacktrace::parse_stacktrace(&report.stacktrace)?;
report.go_report = sanitizers_stderr
Expand All @@ -177,6 +177,14 @@ fn main() -> Result<()> {
if let Some(exception) = GoPanic::parse_exception(&sanitizers_stderr) {
report.execution_class = exception;
}
} else if let Ok(raw_stacktrace) = RustStacktrace::extract_stacktrace(&sanitizers_stderr) {
// If it is possible to extract Rust stacktrace, it is Rust.
report.stacktrace = raw_stacktrace;
stacktrace = RustStacktrace::parse_stacktrace(&report.stacktrace)?;
report.rust_report = sanitizers_stderr
.split('\n')
.map(|l| l.trim_end().to_string())
.collect();
} else {
// Get ASAN report.
let san_stderr_list: Vec<String> = sanitizers_stderr
Expand Down
10 changes: 10 additions & 0 deletions docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ Run casr-san:
If you are using casr-san in docker container modify your seccomp profile to allow
personality syscall (details can be found [here](https://docs.docker.com/engine/security/seccomp/)).

If you are using casr-san to get CASR report for Rust fuzz target, you can choose between
ASAN stacktrace or Rust backtrace to analyze. If environment variable
`RUST_BACKTRACE=(1|full)` is specified, then Rust backtrace is considered.

## casr-ubsan

Triage errors found by UndefinedBehaviorSanitizer and create CASR reports (.casrep)
Expand Down Expand Up @@ -444,6 +448,9 @@ binary with `casr-gdb`:
Thus, `casr-afl` will generate GDB crash report for each unique ASAN crash. So,
you can estimate crash severity for program built without sanitizers.

You can set environment variable `RUST_BACKTRACE=(1|full)` for `casr-afl`. This
variable may be used by [casr-san](#casr-san).

## casr-libfuzzer

Triage crashes found by libFuzzer based fuzzer (C/C++/go-fuzz/Atheris/Jazzer)
Expand Down Expand Up @@ -483,6 +490,9 @@ Atheris example:
$ cp casr/tests/casr_tests/python/yaml_fuzzer.py .
$ casr-libfuzzer -i casr/tests/casr_tests/casrep/atheris_crashes_ruamel_yaml -o casr/tests/tmp_tests_casr/casr_libfuzzer_atheris_out -- ./yaml_fuzzer.py

You can set environment variable `RUST_BACKTRACE=(1|full)` for `casr-libfuzzer`. This
variable may be used by [casr-san](#casr-san).

## casr-dojo

Tool for uploading new and unique CASR reports to DefectDojo
Expand Down
2 changes: 2 additions & 0 deletions libcasr/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ pub const STACK_FRAME_FUNCTION_IGNORE_REGEXES_RUST: &[&str] = &[
r"^core::panicking",
r"^core::result",
r"^panic_abort::",
r"^__rust_try",
];

/// Regular expressions for Go functions to be ignored.
Expand Down Expand Up @@ -238,6 +239,7 @@ pub const STACK_FRAME_FILEPATH_IGNORE_REGEXES_RUST: &[&str] = &[
r".*/rust(|c)/",
// AFL
r".*/afl-.*/.*\.rs",
r".*/libfuzzer-sys-.*/.*\.rs",
];

/// Regular expressions for paths to Go files that should be ignored.
Expand Down
4 changes: 2 additions & 2 deletions libcasr/src/go.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
use crate::exception::Exception;
use crate::stacktrace::ParseStacktrace;

use crate::error::*;
use crate::error::{Error, Result};
use crate::execution_class::ExecutionClass;
use crate::stacktrace::*;
use crate::stacktrace::StacktraceEntry;
use regex::Regex;

/// Structure provides an interface for processing stacktrace from Go panics.
Expand Down
18 changes: 18 additions & 0 deletions libcasr/src/report.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::gdb::GdbStacktrace;
use crate::go::GoStacktrace;
use crate::java::JavaStacktrace;
use crate::python::PythonStacktrace;
use crate::rust::RustStacktrace;
use crate::stacktrace::*;
use chrono::prelude::*;
use gdb_command::mappings::{MappedFiles, MappedFilesExt};
Expand Down Expand Up @@ -210,6 +211,13 @@ pub struct CrashReport {
)]
#[cfg_attr(feature = "serde", serde(default))]
pub java_report: Vec<String>,
/// Rust report.
#[cfg_attr(
feature = "serde",
serde(rename(serialize = "RustReport", deserialize = "RustReport"))
)]
#[cfg_attr(feature = "serde", serde(default))]
pub rust_report: Vec<String>,
/// Crash line from stack trace: source:line or binary+offset.
#[cfg_attr(
feature = "serde",
Expand Down Expand Up @@ -536,6 +544,8 @@ impl CrashReport {
JavaStacktrace::parse_stacktrace(&self.stacktrace)?
} else if !self.go_report.is_empty() {
GoStacktrace::parse_stacktrace(&self.stacktrace)?
} else if !self.rust_report.is_empty() {
RustStacktrace::parse_stacktrace(&self.stacktrace)?
} else {
GdbStacktrace::parse_stacktrace(&self.stacktrace)?
};
Expand Down Expand Up @@ -709,6 +719,14 @@ impl fmt::Display for CrashReport {
}
}

// RustReport
if !self.rust_report.is_empty() {
report += "\n===RustReport===\n";
for e in self.rust_report.iter() {
report += &format!("{e}\n");
}
}

// Source
if !self.source.is_empty() {
report += "\n===Source===\n";
Expand Down
Loading

0 comments on commit 9ed7230

Please sign in to comment.