Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[libcasr] Rust backtrace parsing #146

Merged
merged 9 commits into from
Sep 22, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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() {
anfedotoff marked this conversation as resolved.
Show resolved Hide resolved
select.add_item("RustReport", report.rust_report.join("\n"));
}

if !report.source.is_empty() {
select.add_item("Source", report.source.join("\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 binary. 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
Loading