Skip to content

Commit

Permalink
Handle segfaults and aborts in C# code (#220)
Browse files Browse the repository at this point in the history
* Handle segfaults and aborts in C# code

* add native C# test
  • Loading branch information
headshog authored May 24, 2024
1 parent 552636c commit 5f871aa
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 2 deletions.
3 changes: 3 additions & 0 deletions casr/src/bin/casr-csharp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,9 @@ fn main() -> Result<()> {
if let Some(exception) = CSharpException::parse_exception(&report_str) {
report.execution_class = exception;
}
} else {
// Call casr-san
return util::call_casr_san(&matches, &argv, "casr-csharp");
}

let stacktrace = CSharpStacktrace::parse_stacktrace(&report.stacktrace)?;
Expand Down
10 changes: 8 additions & 2 deletions casr/src/triage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,10 @@ pub fn fuzzing_crash_triage_pipeline(
.join(". ")
);
} else {
bail!("{}", String::from_utf8_lossy(&casr_cluster_d.stderr));
bail!(
"{}",
String::from_utf8_lossy(&casr_cluster_d.stderr).trim_end()
);
}

if !matches.get_flag("no-cluster") {
Expand Down Expand Up @@ -251,7 +254,10 @@ pub fn fuzzing_crash_triage_pipeline(
String::from_utf8_lossy(&casr_cluster_c.stdout).trim_end()
);
} else {
error!("{}", String::from_utf8_lossy(&casr_cluster_c.stderr));
error!(
"{}",
String::from_utf8_lossy(&casr_cluster_c.stderr).trim_end()
);
}

// Remove reports from deduplication phase. They are in clusters now.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#include <iostream>

extern "C" void seg(int len)
{
int a[10];
a[len] = -1;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System;
using System.IO;
using System.Runtime.InteropServices;

public class Program
{
public static void Seg()
{
[DllImport("native.so", EntryPoint="seg")]
static extern void seg(int size);

seg(100000000);
}

public static void Main(string[] args)
{
Seg();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>disable</Nullable>
</PropertyGroup>

</Project>
67 changes: 67 additions & 0 deletions casr/tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5724,6 +5724,73 @@ fn test_casr_csharp() {
}
}

#[test]
#[cfg(target_arch = "x86_64")]
fn test_casr_csharp_native() {
let paths = [
abs_path("tests/casr_tests/csharp/test_casr_csharp_native/test_casr_csharp_native.cs"),
abs_path("tests/casr_tests/csharp/test_casr_csharp_native/test_casr_csharp_native.csproj"),
abs_path("tests/casr_tests/csharp/test_casr_csharp_native/native.cpp"),
abs_path("tests/tmp_tests_casr/test_casr_csharp_native"),
abs_path("tests/tmp_tests_casr/test_casr_csharp_native/test_casr_csharp_native.cs"),
abs_path("tests/tmp_tests_casr/test_casr_csharp_native/test_casr_csharp_native.csproj"),
abs_path("tests/tmp_tests_casr/test_casr_csharp_native/native.so"),
];
let _ = std::fs::create_dir_all(&paths[3]);
let _ = fs::copy(&paths[0], &paths[4]);
let _ = fs::copy(&paths[1], &paths[5]);
let Ok(dotnet_path) = which::which("dotnet") else {
panic!("No dotnet is found.");
};

let _ = Command::new("clang++")
.args([&paths[2], "-g", "-fPIC", "-shared", "-o", &paths[6]])
.output()
.expect("failed to compile .so library");

let _ = Command::new("dotnet")
.args(["build", &paths[5]])
.output()
.expect("failed to build test");

let output = Command::new(*EXE_CASR_CSHARP.read().unwrap())
.args([
"--stdout",
"--",
(dotnet_path.to_str().unwrap()),
format!("{}/bin/Debug/net8.0/test_casr_csharp_native.dll", &paths[3]).as_str(),
])
.env("LD_LIBRARY_PATH", &paths[3])
.output()
.expect("failed to start casr-csharp");

assert!(
output.status.success(),
"Stdout {}.\n Stderr: {}",
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr)
);

let report: Result<Value, _> = serde_json::from_slice(&output.stdout);
if let Ok(report) = report {
let severity_type = report["CrashSeverity"]["Type"].as_str().unwrap();
let severity_desc = report["CrashSeverity"]["ShortDescription"]
.as_str()
.unwrap()
.to_string();

assert_eq!(19, report["Stacktrace"].as_array().unwrap().iter().count());
assert_eq!(severity_type, "NOT_EXPLOITABLE");
assert_eq!(severity_desc, "AccessViolation");
assert!(report["CrashLine"]
.as_str()
.unwrap()
.contains("native.cpp:6"));
} else {
panic!("Couldn't parse json report file.");
}
}

#[test]
#[cfg(target_arch = "x86_64")]
fn test_casr_afl_csharp() {
Expand Down

0 comments on commit 5f871aa

Please sign in to comment.