clang wrapper extend api
This commit is contained in:
commit
414a66382b
140
.github/workflows/build_and_test.yml
vendored
140
.github/workflows/build_and_test.yml
vendored
@ -1,67 +1,73 @@
|
|||||||
name: Build and Test
|
name: Build and Test
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ main, dev ]
|
branches: [ main, dev ]
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [ main, dev ]
|
branches: [ main, dev ]
|
||||||
|
|
||||||
env:
|
env:
|
||||||
CARGO_TERM_COLOR: always
|
CARGO_TERM_COLOR: always
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
lint:
|
lint:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-latest, windows-latest]
|
os: [ubuntu-latest, windows-latest]
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Cache cargo registry
|
- name: Cache cargo registry
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v2
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.cargo/registry
|
~/.cargo/registry
|
||||||
~/.cargo/git
|
~/.cargo/git
|
||||||
key: clippy-cargo-${{ hashFiles('**/Cargo.toml') }}
|
key: clippy-cargo-${{ hashFiles('**/Cargo.toml') }}
|
||||||
- name: Add clippy
|
- name: Add clippy
|
||||||
run: rustup component add clippy
|
run: rustup component add clippy
|
||||||
- name: Run clippy
|
- name: Run clippy
|
||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
command: clippy
|
command: clippy
|
||||||
args: --all
|
args: --all
|
||||||
ubuntu:
|
ubuntu:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Default Build
|
- name: Default Build
|
||||||
run: cargo build --verbose
|
run: cargo build --verbose
|
||||||
- name: Default Test
|
- name: Default Test
|
||||||
run: cargo test --verbose
|
run: cargo test --verbose
|
||||||
- name: Build all features
|
- name: Build all features
|
||||||
run: cd libafl && cargo build --all-features --verbose
|
run: cd libafl && cargo build --all-features --verbose
|
||||||
- name: Test all features
|
- name: Test all features
|
||||||
run: cd libafl && cargo test --all-features --verbose
|
run: cd libafl && cargo test --all-features --verbose
|
||||||
- name: Build no_std
|
- name: Build no_std
|
||||||
run: cd libafl && cargo build --no-default-features --verbose
|
run: cd libafl && cargo build --no-default-features --verbose
|
||||||
- name: Test no_std
|
- name: Test no_std
|
||||||
run: cd libafl && cargo test --no-default-features --verbose
|
run: cd libafl && cargo test --no-default-features --verbose
|
||||||
- name: Build examples
|
- name: Build examples
|
||||||
run: cargo build --examples --verbose
|
run: cargo build --examples --verbose
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Format
|
- name: Format
|
||||||
run: cargo fmt -- --check
|
run: cargo fmt -- --check
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Build Docs
|
- name: Build Docs
|
||||||
run: cargo doc
|
run: cargo doc
|
||||||
- name: Test Docs
|
- name: Test Docs
|
||||||
run: cargo test --doc
|
run: cargo test --doc
|
||||||
windows:
|
windows:
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Windows Build
|
- name: Windows Build
|
||||||
run: cargo build --verbose
|
run: cargo build --verbose
|
||||||
- name: Windows Test
|
# TODO: Figure out how to properly build stuff with clang
|
||||||
run: cargo test --verbose
|
#- name: Add clang path to $PATH env
|
||||||
|
# if: runner.os == 'Windows'
|
||||||
|
# run: echo "C:\msys64\mingw64\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8
|
||||||
|
#- name: Try if clang works
|
||||||
|
# run: clang -v
|
||||||
|
#- name: Windows Test
|
||||||
|
# run: C:\Rust\.cargo\bin\cargo.exe test --verbose
|
||||||
|
@ -15,4 +15,5 @@ members = [
|
|||||||
"fuzzers/frida_libpng",
|
"fuzzers/frida_libpng",
|
||||||
"fuzzers/libfuzzer_libmozjpeg",
|
"fuzzers/libfuzzer_libmozjpeg",
|
||||||
"fuzzers/libfuzzer_libpng_cmpalloc",
|
"fuzzers/libfuzzer_libpng_cmpalloc",
|
||||||
|
"fuzzers/libfuzzer_windows",
|
||||||
]
|
]
|
||||||
|
@ -1,114 +1,114 @@
|
|||||||
// build.rs
|
// build.rs
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
env,
|
env,
|
||||||
path::Path,
|
path::Path,
|
||||||
process::{exit, Command},
|
process::{exit, Command},
|
||||||
};
|
};
|
||||||
|
|
||||||
const LIBPNG_URL: &str =
|
const LIBPNG_URL: &str =
|
||||||
"https://deac-fra.dl.sourceforge.net/project/libpng/libpng16/1.6.37/libpng-1.6.37.tar.xz";
|
"https://deac-fra.dl.sourceforge.net/project/libpng/libpng16/1.6.37/libpng-1.6.37.tar.xz";
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
if cfg!(windows) {
|
if cfg!(windows) {
|
||||||
println!("cargo:warning=Skipping libpng frida example on Windows");
|
println!("cargo:warning=Skipping libpng frida example on Windows");
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
let out_dir = env::var_os("OUT_DIR").unwrap();
|
let out_dir = env::var_os("OUT_DIR").unwrap();
|
||||||
let cwd = env::current_dir().unwrap().to_string_lossy().to_string();
|
let cwd = env::current_dir().unwrap().to_string_lossy().to_string();
|
||||||
let out_dir = out_dir.to_string_lossy().to_string();
|
let out_dir = out_dir.to_string_lossy().to_string();
|
||||||
let out_dir_path = Path::new(&out_dir);
|
let out_dir_path = Path::new(&out_dir);
|
||||||
std::fs::create_dir_all(&out_dir).expect(&format!("Failed to create {}", &out_dir));
|
std::fs::create_dir_all(&out_dir).expect(&format!("Failed to create {}", &out_dir));
|
||||||
|
|
||||||
println!("cargo:rerun-if-changed=../libfuzzer_runtime/rt.c",);
|
println!("cargo:rerun-if-changed=../libfuzzer_runtime/rt.c",);
|
||||||
println!("cargo:rerun-if-changed=harness.cc");
|
println!("cargo:rerun-if-changed=harness.cc");
|
||||||
|
|
||||||
let libpng = format!("{}/libpng-1.6.37", &out_dir);
|
let libpng = format!("{}/libpng-1.6.37", &out_dir);
|
||||||
let libpng_path = Path::new(&libpng);
|
let libpng_path = Path::new(&libpng);
|
||||||
let libpng_tar = format!("{}/libpng-1.6.37.tar.xz", &cwd);
|
let libpng_tar = format!("{}/libpng-1.6.37.tar.xz", &cwd);
|
||||||
|
|
||||||
// Enforce clang for its -fsanitize-coverage support.
|
// Enforce clang for its -fsanitize-coverage support.
|
||||||
std::env::set_var("CC", "clang");
|
std::env::set_var("CC", "clang");
|
||||||
std::env::set_var("CXX", "clang++");
|
std::env::set_var("CXX", "clang++");
|
||||||
let ldflags = match env::var("LDFLAGS") {
|
let ldflags = match env::var("LDFLAGS") {
|
||||||
Ok(val) => val,
|
Ok(val) => val,
|
||||||
Err(_) => "".to_string(),
|
Err(_) => "".to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// println!("cargo:warning=output path is {}", libpng);
|
// println!("cargo:warning=output path is {}", libpng);
|
||||||
if !libpng_path.is_dir() {
|
if !libpng_path.is_dir() {
|
||||||
if !Path::new(&libpng_tar).is_file() {
|
if !Path::new(&libpng_tar).is_file() {
|
||||||
println!("cargo:warning=Libpng not found, downloading...");
|
println!("cargo:warning=Libpng not found, downloading...");
|
||||||
// Download libpng
|
// Download libpng
|
||||||
Command::new("wget")
|
Command::new("wget")
|
||||||
.arg("-c")
|
.arg("-c")
|
||||||
.arg(LIBPNG_URL)
|
.arg(LIBPNG_URL)
|
||||||
.arg("-O")
|
.arg("-O")
|
||||||
.arg(&libpng_tar)
|
.arg(&libpng_tar)
|
||||||
.status()
|
.status()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
Command::new("tar")
|
Command::new("tar")
|
||||||
.current_dir(&out_dir_path)
|
.current_dir(&out_dir_path)
|
||||||
.arg("xvf")
|
.arg("xvf")
|
||||||
.arg(&libpng_tar)
|
.arg(&libpng_tar)
|
||||||
.status()
|
.status()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
Command::new(format!("{}/configure", &libpng))
|
Command::new(format!("{}/configure", &libpng))
|
||||||
.current_dir(&libpng_path)
|
.current_dir(&libpng_path)
|
||||||
.args(&[
|
.args(&[
|
||||||
"--disable-shared",
|
"--disable-shared",
|
||||||
&format!("--host={}", env::var("TARGET").unwrap())[..],
|
&format!("--host={}", env::var("TARGET").unwrap())[..],
|
||||||
])
|
])
|
||||||
.env("CC", "clang")
|
.env("CC", "clang")
|
||||||
.env("CXX", "clang++")
|
.env("CXX", "clang++")
|
||||||
.env(
|
.env(
|
||||||
"CFLAGS",
|
"CFLAGS",
|
||||||
"-O3 -g -D_DEFAULT_SOURCE -fPIC -fno-omit-frame-pointer",
|
"-O3 -g -D_DEFAULT_SOURCE -fPIC -fno-omit-frame-pointer",
|
||||||
)
|
)
|
||||||
.env(
|
.env(
|
||||||
"CXXFLAGS",
|
"CXXFLAGS",
|
||||||
"-O3 -g -D_DEFAULT_SOURCE -fPIC -fno-omit-frame-pointer",
|
"-O3 -g -D_DEFAULT_SOURCE -fPIC -fno-omit-frame-pointer",
|
||||||
)
|
)
|
||||||
.env(
|
.env(
|
||||||
"LDFLAGS",
|
"LDFLAGS",
|
||||||
//format!("-g -fPIE -fsanitize=address {}", ldflags),
|
//format!("-g -fPIE -fsanitize=address {}", ldflags),
|
||||||
format!("-g -fPIE {}", ldflags),
|
format!("-g -fPIE {}", ldflags),
|
||||||
)
|
)
|
||||||
.status()
|
.status()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
Command::new("make")
|
Command::new("make")
|
||||||
.current_dir(&libpng_path)
|
.current_dir(&libpng_path)
|
||||||
.status()
|
.status()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
let status = cc::Build::new()
|
let status = cc::Build::new()
|
||||||
.cpp(true)
|
.cpp(true)
|
||||||
.get_compiler()
|
.get_compiler()
|
||||||
.to_command()
|
.to_command()
|
||||||
.current_dir(&cwd)
|
.current_dir(&cwd)
|
||||||
.arg("-I")
|
.arg("-I")
|
||||||
.arg(format!("{}", &libpng))
|
.arg(&libpng)
|
||||||
//.arg("-D")
|
//.arg("-D")
|
||||||
//.arg("HAS_DUMMY_CRASH=1")
|
//.arg("HAS_DUMMY_CRASH=1")
|
||||||
.arg("-fPIC")
|
.arg("-fPIC")
|
||||||
.arg("-shared")
|
.arg("-shared")
|
||||||
.arg(if env::var("CARGO_CFG_TARGET_OS").unwrap() == "android" {
|
.arg(if env::var("CARGO_CFG_TARGET_OS").unwrap() == "android" {
|
||||||
"-static-libstdc++"
|
"-static-libstdc++"
|
||||||
} else {
|
} else {
|
||||||
""
|
""
|
||||||
})
|
})
|
||||||
.arg("-o")
|
.arg("-o")
|
||||||
.arg(format!("{}/libpng-harness.so", &out_dir))
|
.arg(format!("{}/libpng-harness.so", &out_dir))
|
||||||
.arg("./harness.cc")
|
.arg("./harness.cc")
|
||||||
.arg(format!("{}/.libs/libpng16.a", &libpng))
|
.arg(format!("{}/.libs/libpng16.a", &libpng))
|
||||||
.arg("-l")
|
.arg("-l")
|
||||||
.arg("z")
|
.arg("z")
|
||||||
.status()
|
.status()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert!(status.success());
|
assert!(status.success());
|
||||||
|
|
||||||
println!("cargo:rerun-if-changed=build.rs");
|
println!("cargo:rerun-if-changed=build.rs");
|
||||||
}
|
}
|
||||||
|
@ -34,8 +34,6 @@ use frida_gum::{
|
|||||||
};
|
};
|
||||||
use frida_gum::{Gum, MemoryRange, Module, NativePointer, PageProtection};
|
use frida_gum::{Gum, MemoryRange, Module, NativePointer, PageProtection};
|
||||||
|
|
||||||
use libloading;
|
|
||||||
|
|
||||||
use std::{cell::RefCell, env, ffi::c_void, path::PathBuf};
|
use std::{cell::RefCell, env, ffi::c_void, path::PathBuf};
|
||||||
|
|
||||||
/// An helper that feeds FridaInProcessExecutor with user-supplied instrumentation
|
/// An helper that feeds FridaInProcessExecutor with user-supplied instrumentation
|
||||||
@ -351,9 +349,9 @@ where
|
|||||||
));
|
));
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
base: base,
|
base,
|
||||||
stalker: stalker,
|
stalker,
|
||||||
helper: helper,
|
helper,
|
||||||
followed: false,
|
followed: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -464,10 +462,10 @@ unsafe fn fuzz(
|
|||||||
if state.metadata().get::<Tokens>().is_none() {
|
if state.metadata().get::<Tokens>().is_none() {
|
||||||
state.add_metadata(Tokens::new(vec![
|
state.add_metadata(Tokens::new(vec![
|
||||||
vec![137, 80, 78, 71, 13, 10, 26, 10], // PNG header
|
vec![137, 80, 78, 71, 13, 10, 26, 10], // PNG header
|
||||||
"IHDR".as_bytes().to_vec(),
|
b"IHDR".to_vec(),
|
||||||
"IDAT".as_bytes().to_vec(),
|
b"IDAT".to_vec(),
|
||||||
"PLTE".as_bytes().to_vec(),
|
b"PLTE".to_vec(),
|
||||||
"IEND".as_bytes().to_vec(),
|
b"IEND".to_vec(),
|
||||||
]));
|
]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,109 +1,113 @@
|
|||||||
// build.rs
|
// build.rs
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
env,
|
env,
|
||||||
path::Path,
|
path::Path,
|
||||||
process::{exit, Command},
|
process::{exit, Command},
|
||||||
};
|
};
|
||||||
|
|
||||||
const LIBPNG_URL: &str =
|
const LIBPNG_URL: &str =
|
||||||
"https://deac-fra.dl.sourceforge.net/project/libpng/libpng16/1.6.37/libpng-1.6.37.tar.xz";
|
"https://deac-fra.dl.sourceforge.net/project/libpng/libpng16/1.6.37/libpng-1.6.37.tar.xz";
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
if cfg!(windows) {
|
if cfg!(windows) {
|
||||||
println!("cargo:warning=Skipping libpng example on Windows");
|
println!("cargo:warning=Skipping libpng example on Windows");
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
let out_dir = env::var_os("OUT_DIR").unwrap();
|
let out_dir = env::var_os("OUT_DIR").unwrap();
|
||||||
let cwd = env::current_dir().unwrap().to_string_lossy().to_string();
|
let cwd = env::current_dir().unwrap().to_string_lossy().to_string();
|
||||||
let out_dir = out_dir.to_string_lossy().to_string();
|
let out_dir = out_dir.to_string_lossy().to_string();
|
||||||
let out_dir_path = Path::new(&out_dir);
|
let out_dir_path = Path::new(&out_dir);
|
||||||
|
|
||||||
println!("cargo:rerun-if-changed=../libfuzzer_runtime/rt.c",);
|
println!("cargo:rerun-if-changed=../libfuzzer_runtime/rt.c",);
|
||||||
println!("cargo:rerun-if-changed=harness.cc");
|
println!("cargo:rerun-if-changed=harness.cc");
|
||||||
|
|
||||||
let libpng = format!("{}/libpng-1.6.37", &out_dir);
|
let libpng = format!("{}/libpng-1.6.37", &out_dir);
|
||||||
let libpng_path = Path::new(&libpng);
|
let libpng_path = Path::new(&libpng);
|
||||||
let libpng_tar = format!("{}/libpng-1.6.37.tar.xz", &cwd);
|
let libpng_tar = format!("{}/libpng-1.6.37.tar.xz", &cwd);
|
||||||
|
|
||||||
// Enforce clang for its -fsanitize-coverage support.
|
// Enforce clang for its -fsanitize-coverage support.
|
||||||
std::env::set_var("CC", "clang");
|
std::env::set_var("CC", "clang");
|
||||||
std::env::set_var("CXX", "clang++");
|
std::env::set_var("CXX", "clang++");
|
||||||
let ldflags = match env::var("LDFLAGS") {
|
let ldflags = match env::var("LDFLAGS") {
|
||||||
Ok(val) => val,
|
Ok(val) => val,
|
||||||
Err(_) => "".to_string(),
|
Err(_) => "".to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
if !libpng_path.is_dir() {
|
if !libpng_path.is_dir() {
|
||||||
if !Path::new(&libpng_tar).is_file() {
|
if !Path::new(&libpng_tar).is_file() {
|
||||||
println!("cargo:warning=Libpng not found, downloading...");
|
println!("cargo:warning=Libpng not found, downloading...");
|
||||||
// Download libpng
|
// Download libpng
|
||||||
Command::new("wget")
|
Command::new("wget")
|
||||||
.arg("-c")
|
.arg("-c")
|
||||||
.arg(LIBPNG_URL)
|
.arg(LIBPNG_URL)
|
||||||
.arg("-O")
|
.arg("-O")
|
||||||
.arg(&libpng_tar)
|
.arg(&libpng_tar)
|
||||||
.status()
|
.status()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
Command::new("tar")
|
Command::new("tar")
|
||||||
.current_dir(&out_dir_path)
|
.current_dir(&out_dir_path)
|
||||||
.arg("-xvf")
|
.arg("-xvf")
|
||||||
.arg(&libpng_tar)
|
.arg(&libpng_tar)
|
||||||
.status()
|
.status()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
Command::new(format!("{}/configure", &libpng))
|
Command::new(format!("{}/configure", &libpng))
|
||||||
.current_dir(&libpng_path)
|
.current_dir(&libpng_path)
|
||||||
.args(&[
|
.args(&[
|
||||||
"--disable-shared",
|
"--disable-shared",
|
||||||
&format!("--host={}", env::var("TARGET").unwrap())[..],
|
&format!("--host={}", env::var("TARGET").unwrap())[..],
|
||||||
])
|
])
|
||||||
.env("CC", "clang")
|
.env("CC", "clang")
|
||||||
.env("CXX", "clang++")
|
.env("CXX", "clang++")
|
||||||
.env(
|
.env(
|
||||||
"CFLAGS",
|
"CFLAGS",
|
||||||
"-O3 -g -D_DEFAULT_SOURCE -fPIE -fsanitize-coverage=trace-pc-guard",
|
"-O3 -g -D_DEFAULT_SOURCE -fPIE -fsanitize-coverage=trace-pc-guard",
|
||||||
)
|
)
|
||||||
.env(
|
.env(
|
||||||
"CXXFLAGS",
|
"CXXFLAGS",
|
||||||
"-O3 -g -D_DEFAULT_SOURCE -fPIE -fsanitize-coverage=trace-pc-guard",
|
"-O3 -g -D_DEFAULT_SOURCE -fPIE -fsanitize-coverage=trace-pc-guard",
|
||||||
)
|
)
|
||||||
.env(
|
.env(
|
||||||
"LDFLAGS",
|
"LDFLAGS",
|
||||||
format!("-g -fPIE -fsanitize-coverage=trace-pc-guard {}", ldflags),
|
format!("-g -fPIE -fsanitize-coverage=trace-pc-guard {}", ldflags),
|
||||||
)
|
)
|
||||||
.status()
|
.status()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
Command::new("make")
|
Command::new("make")
|
||||||
.current_dir(&libpng_path)
|
.current_dir(&libpng_path)
|
||||||
.status()
|
.status()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
cc::Build::new()
|
cc::Build::new()
|
||||||
.file("../libfuzzer_runtime/rt.c")
|
.file("../libfuzzer_runtime/rt.c")
|
||||||
.compile("libfuzzer-sys");
|
.compile("libfuzzer-sys");
|
||||||
|
|
||||||
cc::Build::new()
|
cc::Build::new()
|
||||||
.include(&libpng_path)
|
.include(&libpng_path)
|
||||||
.cpp(true)
|
.cpp(true)
|
||||||
.flag("-fsanitize-coverage=trace-pc-guard")
|
.flag("-fsanitize-coverage=trace-pc-guard")
|
||||||
// .define("HAS_DUMMY_CRASH", "1")
|
.flag("-Wno-void-pointer-to-int-cast")
|
||||||
.file("./harness.cc")
|
.flag("-Wno-int-to-pointer-cast")
|
||||||
.compile("libfuzzer-harness");
|
.flag("-Wno-sign-compare")
|
||||||
|
.flag("-Wno-format")
|
||||||
println!("cargo:rustc-link-search=native={}", &out_dir);
|
// .define("HAS_DUMMY_CRASH", "1")
|
||||||
println!("cargo:rustc-link-search=native={}/.libs", &libpng);
|
.file("./harness.cc")
|
||||||
println!("cargo:rustc-link-lib=static=png16");
|
.compile("libfuzzer-harness");
|
||||||
|
|
||||||
//Deps for libpng: -pthread -lz -lm
|
println!("cargo:rustc-link-search=native={}", &out_dir);
|
||||||
println!("cargo:rustc-link-lib=dylib=m");
|
println!("cargo:rustc-link-search=native={}/.libs", &libpng);
|
||||||
println!("cargo:rustc-link-lib=dylib=z");
|
println!("cargo:rustc-link-lib=static=png16");
|
||||||
|
|
||||||
//For the C++ harness
|
//Deps for libpng: -pthread -lz -lm
|
||||||
//must by dylib for android
|
println!("cargo:rustc-link-lib=dylib=m");
|
||||||
println!("cargo:rustc-link-lib=dylib=stdc++");
|
println!("cargo:rustc-link-lib=dylib=z");
|
||||||
|
|
||||||
println!("cargo:rerun-if-changed=build.rs");
|
//For the C++ harness
|
||||||
}
|
//must by dylib for android
|
||||||
|
println!("cargo:rustc-link-lib=dylib=stdc++");
|
||||||
|
|
||||||
|
println!("cargo:rerun-if-changed=build.rs");
|
||||||
|
}
|
||||||
|
@ -131,6 +131,10 @@ void __sanitizer_cov_trace_switch(uint64_t val, uint64_t *cases) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define posix_memalign(p, a, s) (((*(p)) = _aligned_malloc((s), (a))), *(p) ?0 :errno)
|
||||||
|
#endif
|
||||||
|
|
||||||
void *malloc(size_t size) {
|
void *malloc(size_t size) {
|
||||||
|
|
||||||
uintptr_t k = (uintptr_t)__builtin_return_address(0);
|
uintptr_t k = (uintptr_t)__builtin_return_address(0);
|
||||||
|
1
fuzzers/libfuzzer_windows/.gitignore
vendored
Normal file
1
fuzzers/libfuzzer_windows/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
libpng-*
|
31
fuzzers/libfuzzer_windows/Cargo.toml
Normal file
31
fuzzers/libfuzzer_windows/Cargo.toml
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
[package]
|
||||||
|
name = "libfuzzer_windows"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Andrea Fioraldi <andreafioraldi@gmail.com>", "Dominik Maier <domenukk@gmail.com>"]
|
||||||
|
edition = "2018"
|
||||||
|
build = "build.rs"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["std"]
|
||||||
|
std = []
|
||||||
|
|
||||||
|
#[profile.release]
|
||||||
|
#lto = true
|
||||||
|
#codegen-units = 1
|
||||||
|
#opt-level = 3
|
||||||
|
#debug = true
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
cc = { version = "1.0", features = ["parallel"] }
|
||||||
|
num_cpus = "1.0"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
libafl = { path = "../../libafl/" }
|
||||||
|
|
||||||
|
[[example]]
|
||||||
|
name = "libfuzzer_windows"
|
||||||
|
path = "./src/fuzzer.rs"
|
||||||
|
test = false
|
||||||
|
bench = false
|
25
fuzzers/libfuzzer_windows/README.md
Normal file
25
fuzzers/libfuzzer_windows/README.md
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# Libfuzzer for libpng
|
||||||
|
|
||||||
|
This folder contains an example fuzzer for libpng, using LLMP for fast multi-process fuzzing and crash detection.
|
||||||
|
To show off crash detection, we added a ud2 instruction to the harness, edit harness.cc if you want a non-crashing example.
|
||||||
|
It has been tested on Linux.
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
To build this example, run `cargo build --example libfuzzer_libpng --release`.
|
||||||
|
This will call (the build.rs)[./builld.rs], which in turn downloads a libpng archive from the web.
|
||||||
|
Then, it will link (the fuzzer)[./src/fuzzer.rs] against (the C++ harness)[./harness.cc] and the instrumented `libpng`.
|
||||||
|
Afterwards, the fuzzer will be ready to run, from `../../target/examples/libfuzzer_libpng`.
|
||||||
|
|
||||||
|
## Run
|
||||||
|
|
||||||
|
The first time you run the binary, the broker will open a tcp port (currently on port `1337`), waiting for fuzzer clients to connect. This port is local and only used for the initial handshake. All further communication happens via shared map, to be independent of the kernel.
|
||||||
|
|
||||||
|
Each following execution will run a fuzzer client.
|
||||||
|
As this example uses in-process fuzzing, we added a Restarting Event Manager (`setup_restarting_mgr`).
|
||||||
|
This means each client will start itself again to listen for crashes and timeouts.
|
||||||
|
By restarting the actual fuzzer, it can recover from these exit conditions.
|
||||||
|
|
||||||
|
In any real-world scenario, you should use `taskset` to pin each client to an empty CPU core, the lib does not pick an empty core automatically (yet).
|
||||||
|
|
||||||
|
For convenience, you may just run `./test.sh` in this folder to test it.
|
58
fuzzers/libfuzzer_windows/build.rs
Normal file
58
fuzzers/libfuzzer_windows/build.rs
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
// build.rs
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
use std::env;
|
||||||
|
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
fn main() {
|
||||||
|
println!("cargo:warning=Skipping libpng windows example on non-Windows");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
fn main() {
|
||||||
|
let out_dir = env::var_os("OUT_DIR").unwrap();
|
||||||
|
let out_dir = out_dir.to_string_lossy().to_string();
|
||||||
|
|
||||||
|
println!("cargo:rerun-if-changed=../libfuzzer_runtime/rt.c",);
|
||||||
|
println!("cargo:rerun-if-changed=harness.cc");
|
||||||
|
|
||||||
|
// Enforce clang for its -fsanitize-coverage support.
|
||||||
|
std::env::set_var("CC", "clang");
|
||||||
|
std::env::set_var("CXX", "clang++");
|
||||||
|
/*let ldflags = match env::var("LDFLAGS") {
|
||||||
|
Ok(val) => val,
|
||||||
|
Err(_) => "".to_string(),
|
||||||
|
};*/
|
||||||
|
|
||||||
|
cc::Build::new()
|
||||||
|
.file("../libfuzzer_runtime/rt.c")
|
||||||
|
.compile("libfuzzer-sys");
|
||||||
|
|
||||||
|
cc::Build::new()
|
||||||
|
.cpp(true)
|
||||||
|
.flag("-fsanitize-coverage=trace-pc-guard")
|
||||||
|
// .define("HAS_DUMMY_CRASH", "1")
|
||||||
|
.flag("-Wno-void-pointer-to-int-cast")
|
||||||
|
.flag("-Wno-pointer-to-int-cast")
|
||||||
|
.flag("-Wno-int-to-pointer-cast")
|
||||||
|
.flag("-Wno-sign-compare")
|
||||||
|
.flag("-Wno-format")
|
||||||
|
.flag("-Wno-unused-variable")
|
||||||
|
.file("./harness.cc")
|
||||||
|
.compile("windows-harness");
|
||||||
|
|
||||||
|
println!("cargo:rustc-link-search=native={}", &out_dir);
|
||||||
|
//println!("cargo:rustc-link-search=native={}/.libs", &libpng);
|
||||||
|
//println!("cargo:rustc-link-lib=static=png16");
|
||||||
|
|
||||||
|
//Deps for libpng: -pthread -lz -lm
|
||||||
|
//println!("cargo:rustc-link-lib=dylib=m");
|
||||||
|
//println!("cargo:rustc-link-lib=dylib=z");
|
||||||
|
|
||||||
|
//For the C++ harness
|
||||||
|
//must by dylib for android
|
||||||
|
//println!("cargo:rustc-link-lib=dylib=stdc++");
|
||||||
|
|
||||||
|
println!("cargo:rerun-if-changed=build.rs");
|
||||||
|
}
|
BIN
fuzzers/libfuzzer_windows/corpus/not_kitty.png
Normal file
BIN
fuzzers/libfuzzer_windows/corpus/not_kitty.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 218 B |
BIN
fuzzers/libfuzzer_windows/corpus/not_kitty_alpha.png
Normal file
BIN
fuzzers/libfuzzer_windows/corpus/not_kitty_alpha.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 376 B |
BIN
fuzzers/libfuzzer_windows/corpus/not_kitty_gamma.png
Normal file
BIN
fuzzers/libfuzzer_windows/corpus/not_kitty_gamma.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 228 B |
BIN
fuzzers/libfuzzer_windows/corpus/not_kitty_icc.png
Normal file
BIN
fuzzers/libfuzzer_windows/corpus/not_kitty_icc.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 427 B |
231
fuzzers/libfuzzer_windows/harness.cc
Normal file
231
fuzzers/libfuzzer_windows/harness.cc
Normal file
@ -0,0 +1,231 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#define STBI_ASSERT(x)
|
||||||
|
#define STBI_NO_SIMD
|
||||||
|
#define STBI_NO_LINEAR
|
||||||
|
#define STBI_NO_STDIO
|
||||||
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
|
#include "stb_image.h"
|
||||||
|
|
||||||
|
int target_func(const uint8_t *buf, size_t size) {
|
||||||
|
|
||||||
|
/*printf("BUF (%ld): ", size);
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
printf("%02X", buf[i]);
|
||||||
|
}
|
||||||
|
printf("\n");*/
|
||||||
|
|
||||||
|
if (size == 0) return 0;
|
||||||
|
|
||||||
|
switch (buf[0]) {
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
if (buf[1] == 0x44) {
|
||||||
|
//__builtin_trap();
|
||||||
|
return 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 0xff:
|
||||||
|
if (buf[2] == 0xff) {
|
||||||
|
if (buf[1] == 0x44) {
|
||||||
|
//*(char *)(0xdeadbeef) = 1;
|
||||||
|
return 9;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int parse_pe(const uint8_t *data, int size)
|
||||||
|
{
|
||||||
|
HANDLE file = NULL;
|
||||||
|
DWORD fileSize = NULL;
|
||||||
|
DWORD bytesRead = NULL;
|
||||||
|
LPVOID fileData = NULL;
|
||||||
|
PIMAGE_DOS_HEADER dosHeader = {};
|
||||||
|
PIMAGE_NT_HEADERS imageNTHeaders = {};
|
||||||
|
PIMAGE_SECTION_HEADER sectionHeader = {};
|
||||||
|
PIMAGE_SECTION_HEADER importSection = {};
|
||||||
|
IMAGE_IMPORT_DESCRIPTOR* importDescriptor = {};
|
||||||
|
PIMAGE_THUNK_DATA thunkData = {};
|
||||||
|
DWORD thunk = NULL;
|
||||||
|
DWORD rawOffset = NULL;
|
||||||
|
|
||||||
|
// allocate heap
|
||||||
|
fileSize = size;
|
||||||
|
fileData = (void *)data;
|
||||||
|
|
||||||
|
// IMAGE_DOS_HEADER
|
||||||
|
dosHeader = (PIMAGE_DOS_HEADER)fileData;
|
||||||
|
|
||||||
|
printf("******* DOS HEADER *******\n");
|
||||||
|
printf("\t0x%x\t\tMagic number\n", dosHeader->e_magic);
|
||||||
|
/*
|
||||||
|
printf("\t0x%x\t\tBytes on last page of file\n", dosHeader->e_cblp);
|
||||||
|
printf("\t0x%x\t\tPages in file\n", dosHeader->e_cp);
|
||||||
|
printf("\t0x%x\t\tRelocations\n", dosHeader->e_crlc);
|
||||||
|
printf("\t0x%x\t\tSize of header in paragraphs\n", dosHeader->e_cparhdr);
|
||||||
|
printf("\t0x%x\t\tMinimum extra paragraphs needed\n", dosHeader->e_minalloc);
|
||||||
|
printf("\t0x%x\t\tMaximum extra paragraphs needed\n", dosHeader->e_maxalloc);
|
||||||
|
printf("\t0x%x\t\tInitial (relative) SS value\n", dosHeader->e_ss);
|
||||||
|
printf("\t0x%x\t\tInitial SP value\n", dosHeader->e_sp);
|
||||||
|
printf("\t0x%x\t\tInitial SP value\n", dosHeader->e_sp);
|
||||||
|
printf("\t0x%x\t\tChecksum\n", dosHeader->e_csum);
|
||||||
|
printf("\t0x%x\t\tInitial IP value\n", dosHeader->e_ip);
|
||||||
|
printf("\t0x%x\t\tInitial (relative) CS value\n", dosHeader->e_cs);
|
||||||
|
printf("\t0x%x\t\tFile address of relocation table\n", dosHeader->e_lfarlc);
|
||||||
|
printf("\t0x%x\t\tOverlay number\n", dosHeader->e_ovno);
|
||||||
|
printf("\t0x%x\t\tOEM identifier (for e_oeminfo)\n", dosHeader->e_oemid);
|
||||||
|
printf("\t0x%x\t\tOEM information; e_oemid specific\n", dosHeader->e_oeminfo);
|
||||||
|
printf("\t0x%x\t\tFile address of new exe header\n", dosHeader->e_lfanew);
|
||||||
|
*/
|
||||||
|
// IMAGE_NT_HEADERS
|
||||||
|
imageNTHeaders = (PIMAGE_NT_HEADERS)((DWORD)fileData + dosHeader->e_lfanew);
|
||||||
|
/*
|
||||||
|
printf("\n******* NT HEADERS *******\n");
|
||||||
|
printf("\t%x\t\tSignature\n", imageNTHeaders->Signature);
|
||||||
|
|
||||||
|
// FILE_HEADER
|
||||||
|
printf("\n******* FILE HEADER *******\n");
|
||||||
|
printf("\t0x%x\t\tMachine\n", imageNTHeaders->FileHeader.Machine);
|
||||||
|
printf("\t0x%x\t\tNumber of Sections\n", imageNTHeaders->FileHeader.NumberOfSections);
|
||||||
|
printf("\t0x%x\tTime Stamp\n", imageNTHeaders->FileHeader.TimeDateStamp);
|
||||||
|
printf("\t0x%x\t\tPointer to Symbol Table\n", imageNTHeaders->FileHeader.PointerToSymbolTable);
|
||||||
|
printf("\t0x%x\t\tNumber of Symbols\n", imageNTHeaders->FileHeader.NumberOfSymbols);
|
||||||
|
printf("\t0x%x\t\tSize of Optional Header\n", imageNTHeaders->FileHeader.SizeOfOptionalHeader);
|
||||||
|
printf("\t0x%x\t\tCharacteristics\n", imageNTHeaders->FileHeader.Characteristics);
|
||||||
|
|
||||||
|
// OPTIONAL_HEADER
|
||||||
|
printf("\n******* OPTIONAL HEADER *******\n");
|
||||||
|
printf("\t0x%x\t\tMagic\n", imageNTHeaders->OptionalHeader.Magic);
|
||||||
|
printf("\t0x%x\t\tMajor Linker Version\n", imageNTHeaders->OptionalHeader.MajorLinkerVersion);
|
||||||
|
printf("\t0x%x\t\tMinor Linker Version\n", imageNTHeaders->OptionalHeader.MinorLinkerVersion);
|
||||||
|
printf("\t0x%x\t\tSize Of Code\n", imageNTHeaders->OptionalHeader.SizeOfCode);
|
||||||
|
printf("\t0x%x\t\tSize Of Initialized Data\n", imageNTHeaders->OptionalHeader.SizeOfInitializedData);
|
||||||
|
printf("\t0x%x\t\tSize Of UnInitialized Data\n", imageNTHeaders->OptionalHeader.SizeOfUninitializedData);
|
||||||
|
printf("\t0x%x\t\tAddress Of Entry Point (.text)\n", imageNTHeaders->OptionalHeader.AddressOfEntryPoint);
|
||||||
|
printf("\t0x%x\t\tBase Of Code\n", imageNTHeaders->OptionalHeader.BaseOfCode);
|
||||||
|
//printf("\t0x%x\t\tBase Of Data\n", imageNTHeaders->OptionalHeader.BaseOfData);
|
||||||
|
printf("\t0x%x\t\tImage Base\n", imageNTHeaders->OptionalHeader.ImageBase);
|
||||||
|
printf("\t0x%x\t\tSection Alignment\n", imageNTHeaders->OptionalHeader.SectionAlignment);
|
||||||
|
printf("\t0x%x\t\tFile Alignment\n", imageNTHeaders->OptionalHeader.FileAlignment);
|
||||||
|
printf("\t0x%x\t\tMajor Operating System Version\n", imageNTHeaders->OptionalHeader.MajorOperatingSystemVersion);
|
||||||
|
printf("\t0x%x\t\tMinor Operating System Version\n", imageNTHeaders->OptionalHeader.MinorOperatingSystemVersion);
|
||||||
|
printf("\t0x%x\t\tMajor Image Version\n", imageNTHeaders->OptionalHeader.MajorImageVersion);
|
||||||
|
printf("\t0x%x\t\tMinor Image Version\n", imageNTHeaders->OptionalHeader.MinorImageVersion);
|
||||||
|
printf("\t0x%x\t\tMajor Subsystem Version\n", imageNTHeaders->OptionalHeader.MajorSubsystemVersion);
|
||||||
|
printf("\t0x%x\t\tMinor Subsystem Version\n", imageNTHeaders->OptionalHeader.MinorSubsystemVersion);
|
||||||
|
printf("\t0x%x\t\tWin32 Version Value\n", imageNTHeaders->OptionalHeader.Win32VersionValue);
|
||||||
|
printf("\t0x%x\t\tSize Of Image\n", imageNTHeaders->OptionalHeader.SizeOfImage);
|
||||||
|
printf("\t0x%x\t\tSize Of Headers\n", imageNTHeaders->OptionalHeader.SizeOfHeaders);
|
||||||
|
printf("\t0x%x\t\tCheckSum\n", imageNTHeaders->OptionalHeader.CheckSum);
|
||||||
|
printf("\t0x%x\t\tSubsystem\n", imageNTHeaders->OptionalHeader.Subsystem);
|
||||||
|
printf("\t0x%x\t\tDllCharacteristics\n", imageNTHeaders->OptionalHeader.DllCharacteristics);
|
||||||
|
printf("\t0x%x\t\tSize Of Stack Reserve\n", imageNTHeaders->OptionalHeader.SizeOfStackReserve);
|
||||||
|
printf("\t0x%x\t\tSize Of Stack Commit\n", imageNTHeaders->OptionalHeader.SizeOfStackCommit);
|
||||||
|
printf("\t0x%x\t\tSize Of Heap Reserve\n", imageNTHeaders->OptionalHeader.SizeOfHeapReserve);
|
||||||
|
printf("\t0x%x\t\tSize Of Heap Commit\n", imageNTHeaders->OptionalHeader.SizeOfHeapCommit);
|
||||||
|
printf("\t0x%x\t\tLoader Flags\n", imageNTHeaders->OptionalHeader.LoaderFlags);
|
||||||
|
printf("\t0x%x\t\tNumber Of Rva And Sizes\n", imageNTHeaders->OptionalHeader.NumberOfRvaAndSizes);
|
||||||
|
|
||||||
|
// DATA_DIRECTORIES
|
||||||
|
printf("\n******* DATA DIRECTORIES *******\n");
|
||||||
|
printf("\tExport Directory Address: 0x%x; Size: 0x%x\n", imageNTHeaders->OptionalHeader.DataDirectory[0].VirtualAddress, imageNTHeaders->OptionalHeader.DataDirectory[0].Size);
|
||||||
|
printf("\tImport Directory Address: 0x%x; Size: 0x%x\n", imageNTHeaders->OptionalHeader.DataDirectory[1].VirtualAddress, imageNTHeaders->OptionalHeader.DataDirectory[1].Size);
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
|
// SECTION_HEADERS
|
||||||
|
printf("\n******* SECTION HEADERS *******\n");
|
||||||
|
// get offset to first section headeer
|
||||||
|
DWORD sectionLocation = (DWORD)imageNTHeaders + sizeof(DWORD) + (DWORD)(sizeof(IMAGE_FILE_HEADER)) + (DWORD)imageNTHeaders->FileHeader.SizeOfOptionalHeader;
|
||||||
|
DWORD sectionSize = (DWORD)sizeof(IMAGE_SECTION_HEADER);
|
||||||
|
|
||||||
|
// get offset to the import directory RVA
|
||||||
|
DWORD importDirectoryRVA = imageNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
|
||||||
|
// print section data
|
||||||
|
for (int i = 0; i < imageNTHeaders->FileHeader.NumberOfSections; i++) {
|
||||||
|
sectionHeader = (PIMAGE_SECTION_HEADER)sectionLocation;
|
||||||
|
printf("\t%s\n", sectionHeader->Name);
|
||||||
|
printf("\t\t0x%x\t\tVirtual Size\n", sectionHeader->Misc.VirtualSize);
|
||||||
|
printf("\t\t0x%x\t\tVirtual Address\n", sectionHeader->VirtualAddress);
|
||||||
|
/*
|
||||||
|
printf("\t\t0x%x\t\tSize Of Raw Data\n", sectionHeader->SizeOfRawData);
|
||||||
|
printf("\t\t0x%x\t\tPointer To Raw Data\n", sectionHeader->PointerToRawData);
|
||||||
|
printf("\t\t0x%x\t\tPointer To Relocations\n", sectionHeader->PointerToRelocations);
|
||||||
|
printf("\t\t0x%x\t\tPointer To Line Numbers\n", sectionHeader->PointerToLinenumbers);
|
||||||
|
printf("\t\t0x%x\t\tNumber Of Relocations\n", sectionHeader->NumberOfRelocations);
|
||||||
|
printf("\t\t0x%x\t\tNumber Of Line Numbers\n", sectionHeader->NumberOfLinenumbers);
|
||||||
|
printf("\t\t0x%x\tCharacteristics\n", sectionHeader->Characteristics);
|
||||||
|
*/
|
||||||
|
// save section that contains import directory table
|
||||||
|
if (importDirectoryRVA >= sectionHeader->VirtualAddress && importDirectoryRVA < sectionHeader->VirtualAddress + sectionHeader->Misc.VirtualSize) {
|
||||||
|
importSection = sectionHeader;
|
||||||
|
}
|
||||||
|
sectionLocation += sectionSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get file offset to import table
|
||||||
|
rawOffset = (DWORD)fileData + importSection->PointerToRawData;
|
||||||
|
|
||||||
|
// get pointer to import descriptor's file offset. Note that the formula for calculating file offset is: imageBaseAddress + pointerToRawDataOfTheSectionContainingRVAofInterest + (RVAofInterest - SectionContainingRVAofInterest.VirtualAddress)
|
||||||
|
importDescriptor = (IMAGE_IMPORT_DESCRIPTOR*)(rawOffset + (imageNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress - importSection->VirtualAddress));
|
||||||
|
|
||||||
|
printf("\n******* DLL IMPORTS *******\n");
|
||||||
|
for (; importDescriptor->Name != 0; importDescriptor++) {
|
||||||
|
// imported dll modules
|
||||||
|
printf("\t%s\n", rawOffset + (importDescriptor->Name - importSection->VirtualAddress));
|
||||||
|
thunk = importDescriptor->OriginalFirstThunk == 0 ? importDescriptor->FirstThunk : importDescriptor->OriginalFirstThunk;
|
||||||
|
thunkData = (PIMAGE_THUNK_DATA)(rawOffset + (thunk - importSection->VirtualAddress));
|
||||||
|
|
||||||
|
// dll exported functions
|
||||||
|
for (; thunkData->u1.AddressOfData != 0; thunkData++) {
|
||||||
|
//a cheap and probably non-reliable way of checking if the function is imported via its ordinal number ¯\_(ツ)_/¯
|
||||||
|
if (thunkData->u1.AddressOfData > 0x80000000) {
|
||||||
|
//show lower bits of the value to get the ordinal ¯\_(ツ)_/¯
|
||||||
|
printf("\t\tOrdinal: %x\n", (WORD)thunkData->u1.AddressOfData);
|
||||||
|
} else {
|
||||||
|
printf("\t\t%s\n", (rawOffset + (thunkData->u1.AddressOfData - importSection->VirtualAddress + 2)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int load_stbi(const uint8_t *data, int size)
|
||||||
|
{
|
||||||
|
int w;
|
||||||
|
int h;
|
||||||
|
int channels;
|
||||||
|
|
||||||
|
const unsigned char * img = stbi_load_from_memory(data, size, &w, &h, &channels, 0);
|
||||||
|
if (img) { stbi_image_free((void *)img); }
|
||||||
|
// STBI_FREE((void *)img); }
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||||
|
//return target_func(Data, Size);
|
||||||
|
|
||||||
|
if(Size > 0x4000) return 0;
|
||||||
|
|
||||||
|
int size = Size;
|
||||||
|
const unsigned char * data = Data;
|
||||||
|
//return load_stbi(data, size);
|
||||||
|
return parse_pe(data, size);
|
||||||
|
}
|
||||||
|
|
180
fuzzers/libfuzzer_windows/src/fuzzer.rs
Normal file
180
fuzzers/libfuzzer_windows/src/fuzzer.rs
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
//! A libfuzzer-like fuzzer with llmp-multithreading support and restarts
|
||||||
|
//! The example harness is built for libpng.
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
use std::{env, path::PathBuf};
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
use libafl::{
|
||||||
|
bolts::{shmem::Win32ShMem, tuples::tuple_list},
|
||||||
|
corpus::{
|
||||||
|
Corpus, InMemoryCorpus, IndexesLenTimeMinimizerCorpusScheduler, OnDiskCorpus,
|
||||||
|
QueueCorpusScheduler,
|
||||||
|
},
|
||||||
|
events::setup_restarting_mgr,
|
||||||
|
executors::{inprocess::InProcessExecutor, ExitKind},
|
||||||
|
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
||||||
|
fuzzer::{Fuzzer, HasCorpusScheduler, StdFuzzer},
|
||||||
|
mutators::{scheduled::HavocBytesMutator, token_mutations::Tokens},
|
||||||
|
observers::{HitcountsMapObserver, StdMapObserver, TimeObserver},
|
||||||
|
stages::mutational::StdMutationalStage,
|
||||||
|
state::{HasCorpus, HasMetadata, State},
|
||||||
|
stats::SimpleStats,
|
||||||
|
utils::{current_nanos, StdRand},
|
||||||
|
Error,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// We will interact with a C++ target, so use external c functionality
|
||||||
|
#[cfg(windows)]
|
||||||
|
extern "C" {
|
||||||
|
/// int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)
|
||||||
|
fn LLVMFuzzerTestOneInput(data: *const u8, size: usize) -> i32;
|
||||||
|
|
||||||
|
// afl_libfuzzer_init calls LLVMFUzzerInitialize()
|
||||||
|
fn afl_libfuzzer_init() -> i32;
|
||||||
|
|
||||||
|
static __lafl_edges_map: *mut u8;
|
||||||
|
static __lafl_cmp_map: *mut u8;
|
||||||
|
static __lafl_max_edges_size: u32;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The main fn, usually parsing parameters, and starting the fuzzer
|
||||||
|
pub fn main() {
|
||||||
|
// Registry the metadata types used in this fuzzer
|
||||||
|
// Needed only on no_std
|
||||||
|
//RegistryBuilder::register::<Tokens>();
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
println!(
|
||||||
|
"Workdir: {:?}",
|
||||||
|
env::current_dir().unwrap().to_string_lossy().to_string()
|
||||||
|
);
|
||||||
|
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
todo!("Example currently only supports Windows.");
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
fuzz(
|
||||||
|
vec![PathBuf::from("./corpus")],
|
||||||
|
PathBuf::from("./crashes"),
|
||||||
|
1337,
|
||||||
|
)
|
||||||
|
.expect("An error occurred while fuzzing");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Not supported on unix right now
|
||||||
|
//#[cfg(cfg)]
|
||||||
|
//fn fuzz(_corpus_dirs: Vec<PathBuf>, _objective_dir: PathBuf, _broker_port: u16) -> Result<(), ()> {
|
||||||
|
// todo!("Example not supported on Unix");
|
||||||
|
//}
|
||||||
|
|
||||||
|
/// The actual fuzzer
|
||||||
|
#[cfg(windows)]
|
||||||
|
fn fuzz(corpus_dirs: Vec<PathBuf>, objective_dir: PathBuf, broker_port: u16) -> Result<(), Error> {
|
||||||
|
// The wrapped harness function, calling out to the LLVM-style harness
|
||||||
|
let mut harness = |buf: &[u8]| {
|
||||||
|
unsafe { LLVMFuzzerTestOneInput(buf.as_ptr(), buf.len()) };
|
||||||
|
ExitKind::Ok
|
||||||
|
};
|
||||||
|
|
||||||
|
// 'While the stats are state, they are usually used in the broker - which is likely never restarted
|
||||||
|
let stats = SimpleStats::new(|s| println!("{}", s));
|
||||||
|
|
||||||
|
// The restarting state will spawn the same process again as child, then restarted it each time it crashes.
|
||||||
|
let (state, mut restarting_mgr) =
|
||||||
|
match setup_restarting_mgr::<_, _, Win32ShMem, _>(stats, broker_port) {
|
||||||
|
Ok(res) => res,
|
||||||
|
Err(err) => match err {
|
||||||
|
Error::ShuttingDown => {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
panic!("Failed to setup the restarter: {}", err);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create an observation channel using the coverage map
|
||||||
|
let edges_observer = HitcountsMapObserver::new(unsafe {
|
||||||
|
StdMapObserver::new_from_ptr("edges", __lafl_edges_map, __lafl_max_edges_size as usize)
|
||||||
|
});
|
||||||
|
|
||||||
|
// If not restarting, create a State from scratch
|
||||||
|
let mut state = state.unwrap_or_else(|| {
|
||||||
|
State::new(
|
||||||
|
// RNG
|
||||||
|
StdRand::with_seed(current_nanos()),
|
||||||
|
// Corpus that will be evolved, we keep it in memory for performance
|
||||||
|
InMemoryCorpus::new(),
|
||||||
|
// Feedbacks to rate the interestingness of an input
|
||||||
|
tuple_list!(
|
||||||
|
MaxMapFeedback::new_with_observer_track(&edges_observer, true, false),
|
||||||
|
TimeFeedback::new()
|
||||||
|
),
|
||||||
|
// Corpus in which we store solutions (crashes in this example),
|
||||||
|
// on disk so the user can get them after stopping the fuzzer
|
||||||
|
OnDiskCorpus::new(objective_dir).unwrap(),
|
||||||
|
// Feedbacks to recognize an input as solution
|
||||||
|
tuple_list!(CrashFeedback::new(), TimeoutFeedback::new()),
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
println!("We're a client, let's fuzz :)");
|
||||||
|
|
||||||
|
// Create a PNG dictionary if not existing
|
||||||
|
if state.metadata().get::<Tokens>().is_none() {
|
||||||
|
state.add_metadata(Tokens::new(vec![
|
||||||
|
vec![137, 80, 78, 71, 13, 10, 26, 10], // PNG header
|
||||||
|
"IHDR".as_bytes().to_vec(),
|
||||||
|
"IDAT".as_bytes().to_vec(),
|
||||||
|
"PLTE".as_bytes().to_vec(),
|
||||||
|
"IEND".as_bytes().to_vec(),
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup a basic mutator with a mutational stage
|
||||||
|
let mutator = HavocBytesMutator::default();
|
||||||
|
let stage = StdMutationalStage::new(mutator);
|
||||||
|
|
||||||
|
// A fuzzer with just one stage and a minimization+queue policy to get testcasess from the corpus
|
||||||
|
let scheduler = IndexesLenTimeMinimizerCorpusScheduler::new(QueueCorpusScheduler::new());
|
||||||
|
let fuzzer = StdFuzzer::new(scheduler, tuple_list!(stage));
|
||||||
|
|
||||||
|
// Create the executor for an in-process function with just one observer for edge coverage
|
||||||
|
let mut executor = InProcessExecutor::new(
|
||||||
|
"in-process(edges)",
|
||||||
|
&mut harness,
|
||||||
|
tuple_list!(edges_observer, TimeObserver::new("time")),
|
||||||
|
&mut state,
|
||||||
|
&mut restarting_mgr,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
// The actual target run starts here.
|
||||||
|
// Call LLVMFUzzerInitialize() if present.
|
||||||
|
unsafe {
|
||||||
|
if afl_libfuzzer_init() == -1 {
|
||||||
|
println!("Warning: LLVMFuzzerInitialize failed with -1")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// In case the corpus is empty (on first run), reset
|
||||||
|
if state.corpus().count() < 1 {
|
||||||
|
state
|
||||||
|
.load_initial_inputs(
|
||||||
|
&mut executor,
|
||||||
|
&mut restarting_mgr,
|
||||||
|
fuzzer.scheduler(),
|
||||||
|
&corpus_dirs,
|
||||||
|
)
|
||||||
|
.expect(&format!(
|
||||||
|
"Failed to load initial corpus at {:?}",
|
||||||
|
&corpus_dirs
|
||||||
|
));
|
||||||
|
println!("We imported {} inputs from disk.", state.corpus().count());
|
||||||
|
}
|
||||||
|
|
||||||
|
fuzzer.fuzz_loop(&mut state, &mut executor, &mut restarting_mgr)?;
|
||||||
|
|
||||||
|
// Never reached
|
||||||
|
Ok(())
|
||||||
|
}
|
7762
fuzzers/libfuzzer_windows/stb_image.h
Normal file
7762
fuzzers/libfuzzer_windows/stb_image.h
Normal file
File diff suppressed because it is too large
Load Diff
20
fuzzers/libfuzzer_windows/test.bat
Normal file
20
fuzzers/libfuzzer_windows/test.bat
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
mkdir crashes
|
||||||
|
del .\.libfuzzer_test.elf
|
||||||
|
|
||||||
|
cargo build --example libfuzzer_windows --release
|
||||||
|
timeout /T 1
|
||||||
|
cp ..\..\target\release\examples\libfuzzer_windows.exe .\.libfuzzer_test.exe
|
||||||
|
timeout /T 1
|
||||||
|
|
||||||
|
# The broker
|
||||||
|
start .\.libfuzzer_test.exe
|
||||||
|
# Give the broker time to spawn
|
||||||
|
timeout /T 1
|
||||||
|
echo "Spawning client"
|
||||||
|
start .\.libfuzzer_test.exe
|
||||||
|
# .\.libfuzzer_test.exe > nul
|
||||||
|
|
||||||
|
timeout /T 10
|
||||||
|
echo "Finished fuzzing for a bit"
|
||||||
|
TASKKILL /IM .libfuzzer_test.exe
|
||||||
|
del .libfuzzer_test.exe
|
@ -102,6 +102,7 @@ use crate::{
|
|||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(all(unix, feature = "std"))]
|
||||||
use super::shmem::HasFd;
|
use super::shmem::HasFd;
|
||||||
|
|
||||||
/// We'll start off with 256 megabyte maps per fuzzer client
|
/// We'll start off with 256 megabyte maps per fuzzer client
|
||||||
@ -450,6 +451,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(all(unix, feature = "std"))]
|
||||||
impl<SH> LlmpConnection<SH>
|
impl<SH> LlmpConnection<SH>
|
||||||
where
|
where
|
||||||
SH: ShMem + HasFd,
|
SH: ShMem + HasFd,
|
||||||
@ -1888,6 +1890,7 @@ where
|
|||||||
/// `n` clients connect to a broker. They share an outgoing map with the broker,
|
/// `n` clients connect to a broker. They share an outgoing map with the broker,
|
||||||
/// and get incoming messages from the shared broker bus
|
/// and get incoming messages from the shared broker bus
|
||||||
/// If the Shm has a fd, we can attach to it.
|
/// If the Shm has a fd, we can attach to it.
|
||||||
|
#[cfg(all(unix, feature = "std"))]
|
||||||
impl<SH> LlmpClient<SH>
|
impl<SH> LlmpClient<SH>
|
||||||
where
|
where
|
||||||
SH: ShMem + HasFd,
|
SH: ShMem + HasFd,
|
||||||
|
@ -1,332 +1,334 @@
|
|||||||
pub use crate::bolts::bindings::windows::win32::debug::EXCEPTION_POINTERS;
|
pub use crate::bolts::bindings::windows::win32::debug::EXCEPTION_POINTERS;
|
||||||
|
|
||||||
use crate::{bolts::bindings::windows::win32::debug::SetUnhandledExceptionFilter, Error};
|
use crate::{bolts::bindings::windows::win32::debug::SetUnhandledExceptionFilter, Error};
|
||||||
|
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use core::{
|
use core::{
|
||||||
cell::UnsafeCell,
|
cell::UnsafeCell,
|
||||||
convert::TryFrom,
|
convert::TryFrom,
|
||||||
fmt::{self, Display, Formatter},
|
fmt::{self, Display, Formatter},
|
||||||
ptr::write_volatile,
|
ptr::write_volatile,
|
||||||
sync::atomic::{compiler_fence, Ordering},
|
sync::atomic::{compiler_fence, Ordering},
|
||||||
};
|
};
|
||||||
use std::os::raw::{c_long, c_void};
|
use std::os::raw::{c_long, c_void};
|
||||||
|
|
||||||
use num_enum::{IntoPrimitive, TryFromPrimitive};
|
use num_enum::{IntoPrimitive, TryFromPrimitive};
|
||||||
|
|
||||||
//const EXCEPTION_CONTINUE_EXECUTION: c_long = -1;
|
//const EXCEPTION_CONTINUE_EXECUTION: c_long = -1;
|
||||||
//const EXCEPTION_CONTINUE_SEARCH: c_long = 0;
|
//const EXCEPTION_CONTINUE_SEARCH: c_long = 0;
|
||||||
const EXCEPTION_EXECUTE_HANDLER: c_long = 1;
|
const EXCEPTION_EXECUTE_HANDLER: c_long = 1;
|
||||||
|
|
||||||
// From https://github.com/wine-mirror/wine/blob/master/include/winnt.h#L611
|
// From https://github.com/wine-mirror/wine/blob/master/include/winnt.h#L611
|
||||||
pub const STATUS_WAIT_0: u32 = 0x00000000;
|
pub const STATUS_WAIT_0: u32 = 0x00000000;
|
||||||
pub const STATUS_ABANDONED_WAIT_0: u32 = 0x00000080;
|
pub const STATUS_ABANDONED_WAIT_0: u32 = 0x00000080;
|
||||||
pub const STATUS_USER_APC: u32 = 0x000000C0;
|
pub const STATUS_USER_APC: u32 = 0x000000C0;
|
||||||
pub const STATUS_TIMEOUT: u32 = 0x00000102;
|
pub const STATUS_TIMEOUT: u32 = 0x00000102;
|
||||||
pub const STATUS_PENDING: u32 = 0x00000103;
|
pub const STATUS_PENDING: u32 = 0x00000103;
|
||||||
pub const STATUS_SEGMENT_NOTIFICATION: u32 = 0x40000005;
|
pub const STATUS_SEGMENT_NOTIFICATION: u32 = 0x40000005;
|
||||||
pub const STATUS_FATAL_APP_EXIT: u32 = 0x40000015;
|
pub const STATUS_FATAL_APP_EXIT: u32 = 0x40000015;
|
||||||
pub const STATUS_GUARD_PAGE_VIOLATION: u32 = 0x80000001;
|
pub const STATUS_GUARD_PAGE_VIOLATION: u32 = 0x80000001;
|
||||||
pub const STATUS_DATATYPE_MISALIGNMENT: u32 = 0x80000002;
|
pub const STATUS_DATATYPE_MISALIGNMENT: u32 = 0x80000002;
|
||||||
pub const STATUS_BREAKPOINT: u32 = 0x80000003;
|
pub const STATUS_BREAKPOINT: u32 = 0x80000003;
|
||||||
pub const STATUS_SINGLE_STEP: u32 = 0x80000004;
|
pub const STATUS_SINGLE_STEP: u32 = 0x80000004;
|
||||||
pub const STATUS_LONGJUMP: u32 = 0x80000026;
|
pub const STATUS_LONGJUMP: u32 = 0x80000026;
|
||||||
pub const STATUS_UNWIND_CONSOLIDATE: u32 = 0x80000029;
|
pub const STATUS_UNWIND_CONSOLIDATE: u32 = 0x80000029;
|
||||||
pub const STATUS_ACCESS_VIOLATION: u32 = 0xC0000005;
|
pub const STATUS_ACCESS_VIOLATION: u32 = 0xC0000005;
|
||||||
pub const STATUS_IN_PAGE_ERROR: u32 = 0xC0000006;
|
pub const STATUS_IN_PAGE_ERROR: u32 = 0xC0000006;
|
||||||
pub const STATUS_INVALID_HANDLE: u32 = 0xC0000008;
|
pub const STATUS_INVALID_HANDLE: u32 = 0xC0000008;
|
||||||
pub const STATUS_NO_MEMORY: u32 = 0xC0000017;
|
pub const STATUS_NO_MEMORY: u32 = 0xC0000017;
|
||||||
pub const STATUS_ILLEGAL_INSTRUCTION: u32 = 0xC000001D;
|
pub const STATUS_ILLEGAL_INSTRUCTION: u32 = 0xC000001D;
|
||||||
pub const STATUS_NONCONTINUABLE_EXCEPTION: u32 = 0xC0000025;
|
pub const STATUS_NONCONTINUABLE_EXCEPTION: u32 = 0xC0000025;
|
||||||
pub const STATUS_INVALID_DISPOSITION: u32 = 0xC0000026;
|
pub const STATUS_INVALID_DISPOSITION: u32 = 0xC0000026;
|
||||||
pub const STATUS_ARRAY_BOUNDS_EXCEEDED: u32 = 0xC000008C;
|
pub const STATUS_ARRAY_BOUNDS_EXCEEDED: u32 = 0xC000008C;
|
||||||
pub const STATUS_FLOAT_DENORMAL_OPERAND: u32 = 0xC000008D;
|
pub const STATUS_FLOAT_DENORMAL_OPERAND: u32 = 0xC000008D;
|
||||||
pub const STATUS_FLOAT_DIVIDE_BY_ZERO: u32 = 0xC000008E;
|
pub const STATUS_FLOAT_DIVIDE_BY_ZERO: u32 = 0xC000008E;
|
||||||
pub const STATUS_FLOAT_INEXACT_RESULT: u32 = 0xC000008F;
|
pub const STATUS_FLOAT_INEXACT_RESULT: u32 = 0xC000008F;
|
||||||
pub const STATUS_FLOAT_INVALID_OPERATION: u32 = 0xC0000090;
|
pub const STATUS_FLOAT_INVALID_OPERATION: u32 = 0xC0000090;
|
||||||
pub const STATUS_FLOAT_OVERFLOW: u32 = 0xC0000091;
|
pub const STATUS_FLOAT_OVERFLOW: u32 = 0xC0000091;
|
||||||
pub const STATUS_FLOAT_STACK_CHECK: u32 = 0xC0000092;
|
pub const STATUS_FLOAT_STACK_CHECK: u32 = 0xC0000092;
|
||||||
pub const STATUS_FLOAT_UNDERFLOW: u32 = 0xC0000093;
|
pub const STATUS_FLOAT_UNDERFLOW: u32 = 0xC0000093;
|
||||||
pub const STATUS_INTEGER_DIVIDE_BY_ZERO: u32 = 0xC0000094;
|
pub const STATUS_INTEGER_DIVIDE_BY_ZERO: u32 = 0xC0000094;
|
||||||
pub const STATUS_INTEGER_OVERFLOW: u32 = 0xC0000095;
|
pub const STATUS_INTEGER_OVERFLOW: u32 = 0xC0000095;
|
||||||
pub const STATUS_PRIVILEGED_INSTRUCTION: u32 = 0xC0000096;
|
pub const STATUS_PRIVILEGED_INSTRUCTION: u32 = 0xC0000096;
|
||||||
pub const STATUS_STACK_OVERFLOW: u32 = 0xC00000FD;
|
pub const STATUS_STACK_OVERFLOW: u32 = 0xC00000FD;
|
||||||
pub const STATUS_DLL_NOT_FOUND: u32 = 0xC0000135;
|
pub const STATUS_DLL_NOT_FOUND: u32 = 0xC0000135;
|
||||||
pub const STATUS_ORDINAL_NOT_FOUND: u32 = 0xC0000138;
|
pub const STATUS_ORDINAL_NOT_FOUND: u32 = 0xC0000138;
|
||||||
pub const STATUS_ENTRYPOINT_NOT_FOUND: u32 = 0xC0000139;
|
pub const STATUS_ENTRYPOINT_NOT_FOUND: u32 = 0xC0000139;
|
||||||
pub const STATUS_CONTROL_C_EXIT: u32 = 0xC000013A;
|
pub const STATUS_CONTROL_C_EXIT: u32 = 0xC000013A;
|
||||||
pub const STATUS_DLL_INIT_FAILED: u32 = 0xC0000142;
|
pub const STATUS_DLL_INIT_FAILED: u32 = 0xC0000142;
|
||||||
pub const STATUS_FLOAT_MULTIPLE_FAULTS: u32 = 0xC00002B4;
|
pub const STATUS_FLOAT_MULTIPLE_FAULTS: u32 = 0xC00002B4;
|
||||||
pub const STATUS_FLOAT_MULTIPLE_TRAPS: u32 = 0xC00002B5;
|
pub const STATUS_FLOAT_MULTIPLE_TRAPS: u32 = 0xC00002B5;
|
||||||
pub const STATUS_REG_NAT_CONSUMPTION: u32 = 0xC00002C9;
|
pub const STATUS_REG_NAT_CONSUMPTION: u32 = 0xC00002C9;
|
||||||
pub const STATUS_HEAP_CORRUPTION: u32 = 0xC0000374;
|
pub const STATUS_HEAP_CORRUPTION: u32 = 0xC0000374;
|
||||||
pub const STATUS_STACK_BUFFER_OVERRUN: u32 = 0xC0000409;
|
pub const STATUS_STACK_BUFFER_OVERRUN: u32 = 0xC0000409;
|
||||||
pub const STATUS_INVALID_CRUNTIME_PARAMETER: u32 = 0xC0000417;
|
pub const STATUS_INVALID_CRUNTIME_PARAMETER: u32 = 0xC0000417;
|
||||||
pub const STATUS_ASSERTION_FAILURE: u32 = 0xC0000420;
|
pub const STATUS_ASSERTION_FAILURE: u32 = 0xC0000420;
|
||||||
pub const STATUS_SXS_EARLY_DEACTIVATION: u32 = 0xC015000F;
|
pub const STATUS_SXS_EARLY_DEACTIVATION: u32 = 0xC015000F;
|
||||||
pub const STATUS_SXS_INVALID_DEACTIVATION: u32 = 0xC0150010;
|
pub const STATUS_SXS_INVALID_DEACTIVATION: u32 = 0xC0150010;
|
||||||
|
|
||||||
#[derive(IntoPrimitive, TryFromPrimitive, Clone, Copy)]
|
#[derive(IntoPrimitive, TryFromPrimitive, Clone, Copy)]
|
||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
pub enum ExceptionCode {
|
pub enum ExceptionCode {
|
||||||
// From https://docs.microsoft.com/en-us/windows/win32/debug/getexceptioncode
|
// From https://docs.microsoft.com/en-us/windows/win32/debug/getexceptioncode
|
||||||
AccessViolation = STATUS_ACCESS_VIOLATION,
|
AccessViolation = STATUS_ACCESS_VIOLATION,
|
||||||
ArrayBoundsExceeded = STATUS_ARRAY_BOUNDS_EXCEEDED,
|
ArrayBoundsExceeded = STATUS_ARRAY_BOUNDS_EXCEEDED,
|
||||||
Breakpoint = STATUS_BREAKPOINT,
|
Breakpoint = STATUS_BREAKPOINT,
|
||||||
DatatypeMisalignment = STATUS_DATATYPE_MISALIGNMENT,
|
DatatypeMisalignment = STATUS_DATATYPE_MISALIGNMENT,
|
||||||
FltDenormalOperand = STATUS_FLOAT_DENORMAL_OPERAND,
|
FltDenormalOperand = STATUS_FLOAT_DENORMAL_OPERAND,
|
||||||
FltDivideByZero = STATUS_FLOAT_DIVIDE_BY_ZERO,
|
FltDivideByZero = STATUS_FLOAT_DIVIDE_BY_ZERO,
|
||||||
FltInexactResult = STATUS_FLOAT_INEXACT_RESULT,
|
FltInexactResult = STATUS_FLOAT_INEXACT_RESULT,
|
||||||
FltInvalidOperation = STATUS_FLOAT_INVALID_OPERATION,
|
FltInvalidOperation = STATUS_FLOAT_INVALID_OPERATION,
|
||||||
FltOverflow = STATUS_FLOAT_OVERFLOW,
|
FltOverflow = STATUS_FLOAT_OVERFLOW,
|
||||||
FltStackCheck = STATUS_FLOAT_STACK_CHECK,
|
FltStackCheck = STATUS_FLOAT_STACK_CHECK,
|
||||||
FltUnderflow = STATUS_FLOAT_UNDERFLOW,
|
FltUnderflow = STATUS_FLOAT_UNDERFLOW,
|
||||||
GuardPageViolation = STATUS_GUARD_PAGE_VIOLATION,
|
GuardPageViolation = STATUS_GUARD_PAGE_VIOLATION,
|
||||||
IllegalInstruction = STATUS_ILLEGAL_INSTRUCTION,
|
IllegalInstruction = STATUS_ILLEGAL_INSTRUCTION,
|
||||||
InPageError = STATUS_IN_PAGE_ERROR,
|
InPageError = STATUS_IN_PAGE_ERROR,
|
||||||
IntegerDivideByZero = STATUS_INTEGER_DIVIDE_BY_ZERO,
|
IntegerDivideByZero = STATUS_INTEGER_DIVIDE_BY_ZERO,
|
||||||
IntegerOverflow = STATUS_INTEGER_OVERFLOW,
|
IntegerOverflow = STATUS_INTEGER_OVERFLOW,
|
||||||
InvalidDisposition = STATUS_INVALID_DISPOSITION,
|
InvalidDisposition = STATUS_INVALID_DISPOSITION,
|
||||||
InvalidHandle = STATUS_INVALID_HANDLE,
|
InvalidHandle = STATUS_INVALID_HANDLE,
|
||||||
NoncontinuableException = STATUS_NONCONTINUABLE_EXCEPTION,
|
NoncontinuableException = STATUS_NONCONTINUABLE_EXCEPTION,
|
||||||
PrivilegedInstruction = STATUS_PRIVILEGED_INSTRUCTION,
|
PrivilegedInstruction = STATUS_PRIVILEGED_INSTRUCTION,
|
||||||
SingleStep = STATUS_SINGLE_STEP,
|
SingleStep = STATUS_SINGLE_STEP,
|
||||||
StackOverflow = STATUS_STACK_OVERFLOW,
|
StackOverflow = STATUS_STACK_OVERFLOW,
|
||||||
UnwindConsolidate = STATUS_UNWIND_CONSOLIDATE,
|
UnwindConsolidate = STATUS_UNWIND_CONSOLIDATE,
|
||||||
// Addition exceptions
|
// Addition exceptions
|
||||||
Wait0 = STATUS_WAIT_0,
|
Wait0 = STATUS_WAIT_0,
|
||||||
AbandonedWait0 = STATUS_ABANDONED_WAIT_0,
|
AbandonedWait0 = STATUS_ABANDONED_WAIT_0,
|
||||||
UserAPC = STATUS_USER_APC,
|
UserAPC = STATUS_USER_APC,
|
||||||
Timeout = STATUS_TIMEOUT,
|
Timeout = STATUS_TIMEOUT,
|
||||||
Pending = STATUS_PENDING,
|
Pending = STATUS_PENDING,
|
||||||
SegmentNotification = STATUS_SEGMENT_NOTIFICATION,
|
SegmentNotification = STATUS_SEGMENT_NOTIFICATION,
|
||||||
FatalAppExit = STATUS_FATAL_APP_EXIT,
|
FatalAppExit = STATUS_FATAL_APP_EXIT,
|
||||||
Longjump = STATUS_LONGJUMP,
|
Longjump = STATUS_LONGJUMP,
|
||||||
DLLNotFound = STATUS_DLL_NOT_FOUND,
|
DLLNotFound = STATUS_DLL_NOT_FOUND,
|
||||||
OrdinalNotFound = STATUS_ORDINAL_NOT_FOUND,
|
OrdinalNotFound = STATUS_ORDINAL_NOT_FOUND,
|
||||||
EntryPointNotFound = STATUS_ENTRYPOINT_NOT_FOUND,
|
EntryPointNotFound = STATUS_ENTRYPOINT_NOT_FOUND,
|
||||||
ControlCExit = STATUS_CONTROL_C_EXIT,
|
ControlCExit = STATUS_CONTROL_C_EXIT,
|
||||||
DllInitFailed = STATUS_DLL_INIT_FAILED,
|
DllInitFailed = STATUS_DLL_INIT_FAILED,
|
||||||
FltMultipleFaults = STATUS_FLOAT_MULTIPLE_FAULTS,
|
FltMultipleFaults = STATUS_FLOAT_MULTIPLE_FAULTS,
|
||||||
FltMultipleTraps = STATUS_FLOAT_MULTIPLE_TRAPS,
|
FltMultipleTraps = STATUS_FLOAT_MULTIPLE_TRAPS,
|
||||||
RegNatConsumption = STATUS_REG_NAT_CONSUMPTION,
|
RegNatConsumption = STATUS_REG_NAT_CONSUMPTION,
|
||||||
HeapCorruption = STATUS_HEAP_CORRUPTION,
|
HeapCorruption = STATUS_HEAP_CORRUPTION,
|
||||||
StackBufferOverrun = STATUS_STACK_BUFFER_OVERRUN,
|
StackBufferOverrun = STATUS_STACK_BUFFER_OVERRUN,
|
||||||
InvalidCRuntimeParameter = STATUS_INVALID_CRUNTIME_PARAMETER,
|
InvalidCRuntimeParameter = STATUS_INVALID_CRUNTIME_PARAMETER,
|
||||||
AssertionFailure = STATUS_ASSERTION_FAILURE,
|
AssertionFailure = STATUS_ASSERTION_FAILURE,
|
||||||
SXSEarlyDeactivation = STATUS_SXS_EARLY_DEACTIVATION,
|
SXSEarlyDeactivation = STATUS_SXS_EARLY_DEACTIVATION,
|
||||||
SXSInvalidDeactivation = STATUS_SXS_INVALID_DEACTIVATION,
|
SXSInvalidDeactivation = STATUS_SXS_INVALID_DEACTIVATION,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub static CRASH_EXCEPTIONS: &[ExceptionCode] = &[
|
pub static CRASH_EXCEPTIONS: &[ExceptionCode] = &[
|
||||||
ExceptionCode::AccessViolation,
|
ExceptionCode::AccessViolation,
|
||||||
ExceptionCode::ArrayBoundsExceeded,
|
ExceptionCode::ArrayBoundsExceeded,
|
||||||
ExceptionCode::FltDivideByZero,
|
ExceptionCode::FltDivideByZero,
|
||||||
ExceptionCode::GuardPageViolation,
|
ExceptionCode::GuardPageViolation,
|
||||||
ExceptionCode::IllegalInstruction,
|
ExceptionCode::IllegalInstruction,
|
||||||
ExceptionCode::InPageError,
|
ExceptionCode::InPageError,
|
||||||
ExceptionCode::IntegerDivideByZero,
|
ExceptionCode::IntegerDivideByZero,
|
||||||
ExceptionCode::InvalidHandle,
|
ExceptionCode::InvalidHandle,
|
||||||
ExceptionCode::NoncontinuableException,
|
ExceptionCode::NoncontinuableException,
|
||||||
ExceptionCode::PrivilegedInstruction,
|
ExceptionCode::PrivilegedInstruction,
|
||||||
ExceptionCode::StackOverflow,
|
ExceptionCode::StackOverflow,
|
||||||
ExceptionCode::HeapCorruption,
|
ExceptionCode::HeapCorruption,
|
||||||
ExceptionCode::StackBufferOverrun,
|
ExceptionCode::StackBufferOverrun,
|
||||||
ExceptionCode::AssertionFailure,
|
ExceptionCode::AssertionFailure,
|
||||||
];
|
];
|
||||||
|
|
||||||
impl PartialEq for ExceptionCode {
|
impl PartialEq for ExceptionCode {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
*self as u32 == *other as u32
|
*self as u32 == *other as u32
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Eq for ExceptionCode {}
|
impl Eq for ExceptionCode {}
|
||||||
|
|
||||||
unsafe impl Sync for ExceptionCode {}
|
unsafe impl Sync for ExceptionCode {}
|
||||||
|
|
||||||
impl Display for ExceptionCode {
|
impl Display for ExceptionCode {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
|
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
|
||||||
match self {
|
match self {
|
||||||
ExceptionCode::AccessViolation => write!(f, "STATUS_ACCESS_VIOLATION")?,
|
ExceptionCode::AccessViolation => write!(f, "STATUS_ACCESS_VIOLATION")?,
|
||||||
ExceptionCode::ArrayBoundsExceeded => write!(f, "STATUS_ARRAY_BOUNDS_EXCEEDED")?,
|
ExceptionCode::ArrayBoundsExceeded => write!(f, "STATUS_ARRAY_BOUNDS_EXCEEDED")?,
|
||||||
ExceptionCode::Breakpoint => write!(f, "STATUS_BREAKPOINT")?,
|
ExceptionCode::Breakpoint => write!(f, "STATUS_BREAKPOINT")?,
|
||||||
ExceptionCode::DatatypeMisalignment => write!(f, "STATUS_DATATYPE_MISALIGNMENT")?,
|
ExceptionCode::DatatypeMisalignment => write!(f, "STATUS_DATATYPE_MISALIGNMENT")?,
|
||||||
ExceptionCode::FltDenormalOperand => write!(f, "STATUS_FLOAT_DENORMAL_OPERAND")?,
|
ExceptionCode::FltDenormalOperand => write!(f, "STATUS_FLOAT_DENORMAL_OPERAND")?,
|
||||||
ExceptionCode::FltDivideByZero => write!(f, "STATUS_FLOAT_DIVIDE_BY_ZERO")?,
|
ExceptionCode::FltDivideByZero => write!(f, "STATUS_FLOAT_DIVIDE_BY_ZERO")?,
|
||||||
ExceptionCode::FltInexactResult => write!(f, "STATUS_FLOAT_INEXACT_RESULT")?,
|
ExceptionCode::FltInexactResult => write!(f, "STATUS_FLOAT_INEXACT_RESULT")?,
|
||||||
ExceptionCode::FltInvalidOperation => write!(f, "STATUS_FLOAT_INVALID_OPERATION")?,
|
ExceptionCode::FltInvalidOperation => write!(f, "STATUS_FLOAT_INVALID_OPERATION")?,
|
||||||
ExceptionCode::FltOverflow => write!(f, "STATUS_FLOAT_OVERFLOW")?,
|
ExceptionCode::FltOverflow => write!(f, "STATUS_FLOAT_OVERFLOW")?,
|
||||||
ExceptionCode::FltStackCheck => write!(f, "STATUS_FLOAT_STACK_CHECK")?,
|
ExceptionCode::FltStackCheck => write!(f, "STATUS_FLOAT_STACK_CHECK")?,
|
||||||
ExceptionCode::FltUnderflow => write!(f, "STATUS_FLOAT_UNDERFLOW")?,
|
ExceptionCode::FltUnderflow => write!(f, "STATUS_FLOAT_UNDERFLOW")?,
|
||||||
ExceptionCode::GuardPageViolation => write!(f, "STATUS_GUARD_PAGE_VIOLATION")?,
|
ExceptionCode::GuardPageViolation => write!(f, "STATUS_GUARD_PAGE_VIOLATION")?,
|
||||||
ExceptionCode::IllegalInstruction => write!(f, "STATUS_ILLEGAL_INSTRUCTION")?,
|
ExceptionCode::IllegalInstruction => write!(f, "STATUS_ILLEGAL_INSTRUCTION")?,
|
||||||
ExceptionCode::InPageError => write!(f, "STATUS_IN_PAGE_ERROR")?,
|
ExceptionCode::InPageError => write!(f, "STATUS_IN_PAGE_ERROR")?,
|
||||||
ExceptionCode::IntegerDivideByZero => write!(f, "STATUS_INTEGER_DIVIDE_BY_ZERO")?,
|
ExceptionCode::IntegerDivideByZero => write!(f, "STATUS_INTEGER_DIVIDE_BY_ZERO")?,
|
||||||
ExceptionCode::IntegerOverflow => write!(f, "STATUS_INTEGER_OVERFLOW")?,
|
ExceptionCode::IntegerOverflow => write!(f, "STATUS_INTEGER_OVERFLOW")?,
|
||||||
ExceptionCode::InvalidDisposition => write!(f, "STATUS_INVALID_DISPOSITION")?,
|
ExceptionCode::InvalidDisposition => write!(f, "STATUS_INVALID_DISPOSITION")?,
|
||||||
ExceptionCode::InvalidHandle => write!(f, "STATUS_INVALID_HANDLE")?,
|
ExceptionCode::InvalidHandle => write!(f, "STATUS_INVALID_HANDLE")?,
|
||||||
ExceptionCode::NoncontinuableException => write!(f, "STATUS_NONCONTINUABLE_EXCEPTION")?,
|
ExceptionCode::NoncontinuableException => write!(f, "STATUS_NONCONTINUABLE_EXCEPTION")?,
|
||||||
ExceptionCode::PrivilegedInstruction => write!(f, "STATUS_PRIVILEGED_INSTRUCTION")?,
|
ExceptionCode::PrivilegedInstruction => write!(f, "STATUS_PRIVILEGED_INSTRUCTION")?,
|
||||||
ExceptionCode::SingleStep => write!(f, "STATUS_SINGLE_STEP")?,
|
ExceptionCode::SingleStep => write!(f, "STATUS_SINGLE_STEP")?,
|
||||||
ExceptionCode::StackOverflow => write!(f, "STATUS_STACK_OVERFLOW")?,
|
ExceptionCode::StackOverflow => write!(f, "STATUS_STACK_OVERFLOW")?,
|
||||||
ExceptionCode::UnwindConsolidate => write!(f, "STATUS_UNWIND_CONSOLIDATE")?,
|
ExceptionCode::UnwindConsolidate => write!(f, "STATUS_UNWIND_CONSOLIDATE")?,
|
||||||
ExceptionCode::Wait0 => write!(f, "STATUS_WAIT_0")?,
|
ExceptionCode::Wait0 => write!(f, "STATUS_WAIT_0")?,
|
||||||
ExceptionCode::AbandonedWait0 => write!(f, "STATUS_ABANDONED_WAIT_0")?,
|
ExceptionCode::AbandonedWait0 => write!(f, "STATUS_ABANDONED_WAIT_0")?,
|
||||||
ExceptionCode::UserAPC => write!(f, "STATUS_USER_APC")?,
|
ExceptionCode::UserAPC => write!(f, "STATUS_USER_APC")?,
|
||||||
ExceptionCode::Timeout => write!(f, "STATUS_TIMEOUT")?,
|
ExceptionCode::Timeout => write!(f, "STATUS_TIMEOUT")?,
|
||||||
ExceptionCode::Pending => write!(f, "STATUS_PENDING")?,
|
ExceptionCode::Pending => write!(f, "STATUS_PENDING")?,
|
||||||
ExceptionCode::SegmentNotification => write!(f, "STATUS_SEGMENT_NOTIFICATION")?,
|
ExceptionCode::SegmentNotification => write!(f, "STATUS_SEGMENT_NOTIFICATION")?,
|
||||||
ExceptionCode::FatalAppExit => write!(f, "STATUS_FATAL_APP_EXIT")?,
|
ExceptionCode::FatalAppExit => write!(f, "STATUS_FATAL_APP_EXIT")?,
|
||||||
ExceptionCode::Longjump => write!(f, "STATUS_LONGJUMP")?,
|
ExceptionCode::Longjump => write!(f, "STATUS_LONGJUMP")?,
|
||||||
ExceptionCode::DLLNotFound => write!(f, "STATUS_DLL_NOT_FOUND")?,
|
ExceptionCode::DLLNotFound => write!(f, "STATUS_DLL_NOT_FOUND")?,
|
||||||
ExceptionCode::OrdinalNotFound => write!(f, "STATUS_ORDINAL_NOT_FOUND")?,
|
ExceptionCode::OrdinalNotFound => write!(f, "STATUS_ORDINAL_NOT_FOUND")?,
|
||||||
ExceptionCode::EntryPointNotFound => write!(f, "STATUS_ENTRYPOINT_NOT_FOUND")?,
|
ExceptionCode::EntryPointNotFound => write!(f, "STATUS_ENTRYPOINT_NOT_FOUND")?,
|
||||||
ExceptionCode::ControlCExit => write!(f, "STATUS_CONTROL_C_EXIT")?,
|
ExceptionCode::ControlCExit => write!(f, "STATUS_CONTROL_C_EXIT")?,
|
||||||
ExceptionCode::DllInitFailed => write!(f, "STATUS_DLL_INIT_FAILED")?,
|
ExceptionCode::DllInitFailed => write!(f, "STATUS_DLL_INIT_FAILED")?,
|
||||||
ExceptionCode::FltMultipleFaults => write!(f, "STATUS_FLOAT_MULTIPLE_FAULTS")?,
|
ExceptionCode::FltMultipleFaults => write!(f, "STATUS_FLOAT_MULTIPLE_FAULTS")?,
|
||||||
ExceptionCode::FltMultipleTraps => write!(f, "STATUS_FLOAT_MULTIPLE_TRAPS")?,
|
ExceptionCode::FltMultipleTraps => write!(f, "STATUS_FLOAT_MULTIPLE_TRAPS")?,
|
||||||
ExceptionCode::RegNatConsumption => write!(f, "STATUS_REG_NAT_CONSUMPTION")?,
|
ExceptionCode::RegNatConsumption => write!(f, "STATUS_REG_NAT_CONSUMPTION")?,
|
||||||
ExceptionCode::HeapCorruption => write!(f, "STATUS_HEAP_CORRUPTION")?,
|
ExceptionCode::HeapCorruption => write!(f, "STATUS_HEAP_CORRUPTION")?,
|
||||||
ExceptionCode::StackBufferOverrun => write!(f, "STATUS_STACK_BUFFER_OVERRUN")?,
|
ExceptionCode::StackBufferOverrun => write!(f, "STATUS_STACK_BUFFER_OVERRUN")?,
|
||||||
ExceptionCode::InvalidCRuntimeParameter => {
|
ExceptionCode::InvalidCRuntimeParameter => {
|
||||||
write!(f, "STATUS_INVALID_CRUNTIME_PARAMETER")?
|
write!(f, "STATUS_INVALID_CRUNTIME_PARAMETER")?
|
||||||
}
|
}
|
||||||
ExceptionCode::AssertionFailure => write!(f, "STATUS_ASSERTION_FAILURE")?,
|
ExceptionCode::AssertionFailure => write!(f, "STATUS_ASSERTION_FAILURE")?,
|
||||||
ExceptionCode::SXSEarlyDeactivation => write!(f, "STATUS_SXS_EARLY_DEACTIVATION")?,
|
ExceptionCode::SXSEarlyDeactivation => write!(f, "STATUS_SXS_EARLY_DEACTIVATION")?,
|
||||||
ExceptionCode::SXSInvalidDeactivation => write!(f, "STATUS_SXS_INVALID_DEACTIVATION")?,
|
ExceptionCode::SXSInvalidDeactivation => write!(f, "STATUS_SXS_INVALID_DEACTIVATION")?,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub static EXCEPTION_CODES_MAPPING: [ExceptionCode; 45] = [
|
pub static EXCEPTION_CODES_MAPPING: [ExceptionCode; 45] = [
|
||||||
ExceptionCode::AccessViolation,
|
ExceptionCode::AccessViolation,
|
||||||
ExceptionCode::ArrayBoundsExceeded,
|
ExceptionCode::ArrayBoundsExceeded,
|
||||||
ExceptionCode::Breakpoint,
|
ExceptionCode::Breakpoint,
|
||||||
ExceptionCode::DatatypeMisalignment,
|
ExceptionCode::DatatypeMisalignment,
|
||||||
ExceptionCode::FltDenormalOperand,
|
ExceptionCode::FltDenormalOperand,
|
||||||
ExceptionCode::FltDivideByZero,
|
ExceptionCode::FltDivideByZero,
|
||||||
ExceptionCode::FltInexactResult,
|
ExceptionCode::FltInexactResult,
|
||||||
ExceptionCode::FltInvalidOperation,
|
ExceptionCode::FltInvalidOperation,
|
||||||
ExceptionCode::FltOverflow,
|
ExceptionCode::FltOverflow,
|
||||||
ExceptionCode::FltStackCheck,
|
ExceptionCode::FltStackCheck,
|
||||||
ExceptionCode::FltUnderflow,
|
ExceptionCode::FltUnderflow,
|
||||||
ExceptionCode::GuardPageViolation,
|
ExceptionCode::GuardPageViolation,
|
||||||
ExceptionCode::IllegalInstruction,
|
ExceptionCode::IllegalInstruction,
|
||||||
ExceptionCode::InPageError,
|
ExceptionCode::InPageError,
|
||||||
ExceptionCode::IntegerDivideByZero,
|
ExceptionCode::IntegerDivideByZero,
|
||||||
ExceptionCode::IntegerOverflow,
|
ExceptionCode::IntegerOverflow,
|
||||||
ExceptionCode::InvalidDisposition,
|
ExceptionCode::InvalidDisposition,
|
||||||
ExceptionCode::InvalidHandle,
|
ExceptionCode::InvalidHandle,
|
||||||
ExceptionCode::NoncontinuableException,
|
ExceptionCode::NoncontinuableException,
|
||||||
ExceptionCode::PrivilegedInstruction,
|
ExceptionCode::PrivilegedInstruction,
|
||||||
ExceptionCode::SingleStep,
|
ExceptionCode::SingleStep,
|
||||||
ExceptionCode::StackOverflow,
|
ExceptionCode::StackOverflow,
|
||||||
ExceptionCode::UnwindConsolidate,
|
ExceptionCode::UnwindConsolidate,
|
||||||
ExceptionCode::Wait0,
|
ExceptionCode::Wait0,
|
||||||
ExceptionCode::AbandonedWait0,
|
ExceptionCode::AbandonedWait0,
|
||||||
ExceptionCode::UserAPC,
|
ExceptionCode::UserAPC,
|
||||||
ExceptionCode::Timeout,
|
ExceptionCode::Timeout,
|
||||||
ExceptionCode::Pending,
|
ExceptionCode::Pending,
|
||||||
ExceptionCode::SegmentNotification,
|
ExceptionCode::SegmentNotification,
|
||||||
ExceptionCode::FatalAppExit,
|
ExceptionCode::FatalAppExit,
|
||||||
ExceptionCode::Longjump,
|
ExceptionCode::Longjump,
|
||||||
ExceptionCode::DLLNotFound,
|
ExceptionCode::DLLNotFound,
|
||||||
ExceptionCode::OrdinalNotFound,
|
ExceptionCode::OrdinalNotFound,
|
||||||
ExceptionCode::EntryPointNotFound,
|
ExceptionCode::EntryPointNotFound,
|
||||||
ExceptionCode::ControlCExit,
|
ExceptionCode::ControlCExit,
|
||||||
ExceptionCode::DllInitFailed,
|
ExceptionCode::DllInitFailed,
|
||||||
ExceptionCode::FltMultipleFaults,
|
ExceptionCode::FltMultipleFaults,
|
||||||
ExceptionCode::FltMultipleTraps,
|
ExceptionCode::FltMultipleTraps,
|
||||||
ExceptionCode::RegNatConsumption,
|
ExceptionCode::RegNatConsumption,
|
||||||
ExceptionCode::HeapCorruption,
|
ExceptionCode::HeapCorruption,
|
||||||
ExceptionCode::StackBufferOverrun,
|
ExceptionCode::StackBufferOverrun,
|
||||||
ExceptionCode::InvalidCRuntimeParameter,
|
ExceptionCode::InvalidCRuntimeParameter,
|
||||||
ExceptionCode::AssertionFailure,
|
ExceptionCode::AssertionFailure,
|
||||||
ExceptionCode::SXSEarlyDeactivation,
|
ExceptionCode::SXSEarlyDeactivation,
|
||||||
ExceptionCode::SXSInvalidDeactivation,
|
ExceptionCode::SXSInvalidDeactivation,
|
||||||
];
|
];
|
||||||
|
|
||||||
pub trait Handler {
|
pub trait Handler {
|
||||||
/// Handle an exception
|
/// Handle an exception
|
||||||
fn handle(
|
fn handle(
|
||||||
&mut self,
|
&mut self,
|
||||||
exception_code: ExceptionCode,
|
exception_code: ExceptionCode,
|
||||||
exception_pointers: *mut EXCEPTION_POINTERS,
|
exception_pointers: *mut EXCEPTION_POINTERS,
|
||||||
);
|
);
|
||||||
/// Return a list of exceptions to handle
|
/// Return a list of exceptions to handle
|
||||||
fn exceptions(&self) -> Vec<ExceptionCode>;
|
fn exceptions(&self) -> Vec<ExceptionCode>;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct HandlerHolder {
|
struct HandlerHolder {
|
||||||
handler: UnsafeCell<*mut dyn Handler>,
|
handler: UnsafeCell<*mut dyn Handler>,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Send for HandlerHolder {}
|
unsafe impl Send for HandlerHolder {}
|
||||||
|
|
||||||
/// Keep track of which handler is registered for which exception
|
/// Keep track of which handler is registered for which exception
|
||||||
static mut EXCEPTION_HANDLERS: [Option<HandlerHolder>; 64] = [
|
static mut EXCEPTION_HANDLERS: [Option<HandlerHolder>; 64] = [
|
||||||
None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,
|
None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,
|
||||||
None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,
|
None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,
|
||||||
None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,
|
None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,
|
||||||
None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,
|
None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,
|
||||||
];
|
];
|
||||||
|
|
||||||
type NativeHandlerType = extern "system" fn(*mut EXCEPTION_POINTERS) -> c_long;
|
type NativeHandlerType = extern "system" fn(*mut EXCEPTION_POINTERS) -> c_long;
|
||||||
static mut PREVIOUS_HANDLER: Option<NativeHandlerType> = None;
|
static mut PREVIOUS_HANDLER: Option<NativeHandlerType> = None;
|
||||||
|
|
||||||
/// Internal function that is being called whenever an exception arrives (stdcall).
|
/// Internal function that is being called whenever an exception arrives (stdcall).
|
||||||
unsafe extern "system" fn handle_exception(exception_pointers: *mut EXCEPTION_POINTERS) -> c_long {
|
unsafe extern "system" fn handle_exception(exception_pointers: *mut EXCEPTION_POINTERS) -> c_long {
|
||||||
let code = exception_pointers
|
let code = exception_pointers
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.exception_record
|
.exception_record
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.exception_code;
|
.exception_code;
|
||||||
let exception_code = ExceptionCode::try_from(code).unwrap();
|
let exception_code = ExceptionCode::try_from(code).unwrap();
|
||||||
let index = EXCEPTION_CODES_MAPPING
|
let index = EXCEPTION_CODES_MAPPING
|
||||||
.iter()
|
.iter()
|
||||||
.position(|x| *x == exception_code)
|
.position(|x| *x == exception_code)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let ret = match &EXCEPTION_HANDLERS[index] {
|
let ret = match &EXCEPTION_HANDLERS[index] {
|
||||||
Some(handler_holder) => {
|
Some(handler_holder) => {
|
||||||
let handler = &mut **handler_holder.handler.get();
|
let handler = &mut **handler_holder.handler.get();
|
||||||
handler.handle(exception_code, exception_pointers);
|
handler.handle(exception_code, exception_pointers);
|
||||||
EXCEPTION_EXECUTE_HANDLER
|
EXCEPTION_EXECUTE_HANDLER
|
||||||
}
|
}
|
||||||
None => EXCEPTION_EXECUTE_HANDLER,
|
None => EXCEPTION_EXECUTE_HANDLER,
|
||||||
};
|
};
|
||||||
if let Some(prev_handler) = PREVIOUS_HANDLER {
|
if let Some(prev_handler) = PREVIOUS_HANDLER {
|
||||||
prev_handler(exception_pointers)
|
prev_handler(exception_pointers)
|
||||||
} else {
|
} else {
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Setup Win32 exception handlers in a somewhat rusty way.
|
/// Setup Win32 exception handlers in a somewhat rusty way.
|
||||||
pub unsafe fn setup_exception_handler<T: 'static + Handler>(handler: &mut T) -> Result<(), Error> {
|
/// # Safety
|
||||||
let exceptions = handler.exceptions();
|
/// Exception handlers are usually ugly, handle with care!
|
||||||
for exception_code in exceptions {
|
pub unsafe fn setup_exception_handler<T: 'static + Handler>(handler: &mut T) -> Result<(), Error> {
|
||||||
let index = EXCEPTION_CODES_MAPPING
|
let exceptions = handler.exceptions();
|
||||||
.iter()
|
for exception_code in exceptions {
|
||||||
.position(|x| *x == exception_code)
|
let index = EXCEPTION_CODES_MAPPING
|
||||||
.unwrap();
|
.iter()
|
||||||
write_volatile(
|
.position(|x| *x == exception_code)
|
||||||
&mut EXCEPTION_HANDLERS[index],
|
.unwrap();
|
||||||
Some(HandlerHolder {
|
write_volatile(
|
||||||
handler: UnsafeCell::new(handler as *mut dyn Handler),
|
&mut EXCEPTION_HANDLERS[index],
|
||||||
}),
|
Some(HandlerHolder {
|
||||||
);
|
handler: UnsafeCell::new(handler as *mut dyn Handler),
|
||||||
}
|
}),
|
||||||
compiler_fence(Ordering::SeqCst);
|
);
|
||||||
|
}
|
||||||
if let Some(prev) = SetUnhandledExceptionFilter(Some(core::mem::transmute(
|
compiler_fence(Ordering::SeqCst);
|
||||||
handle_exception as *const c_void,
|
|
||||||
))) {
|
if let Some(prev) = SetUnhandledExceptionFilter(Some(core::mem::transmute(
|
||||||
PREVIOUS_HANDLER = Some(core::mem::transmute(prev as *const c_void));
|
handle_exception as *const c_void,
|
||||||
}
|
))) {
|
||||||
Ok(())
|
PREVIOUS_HANDLER = Some(core::mem::transmute(prev as *const c_void));
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
@ -98,6 +98,7 @@ pub trait ShMem: Sized + Debug {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// shared maps that have an id can use this trait
|
/// shared maps that have an id can use this trait
|
||||||
|
//#[cfg(all(unix, feature = "std"))]
|
||||||
pub trait HasFd {
|
pub trait HasFd {
|
||||||
/// Retrieve the id of this shared map
|
/// Retrieve the id of this shared map
|
||||||
fn shm_id(&self) -> i32;
|
fn shm_id(&self) -> i32;
|
||||||
@ -519,9 +520,8 @@ pub mod shmem {
|
|||||||
String::from_utf8_lossy(map_str_bytes)
|
String::from_utf8_lossy(map_str_bytes)
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
let map =
|
let map = MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, map_size) as *mut u8;
|
||||||
MapViewOfFile(handle.clone(), FILE_MAP_ALL_ACCESS, 0, 0, map_size) as *mut u8;
|
if map.is_null() {
|
||||||
if map == ptr::null_mut() {
|
|
||||||
return Err(Error::Unknown(format!(
|
return Err(Error::Unknown(format!(
|
||||||
"Cannot map shared memory {}",
|
"Cannot map shared memory {}",
|
||||||
String::from_utf8_lossy(map_str_bytes)
|
String::from_utf8_lossy(map_str_bytes)
|
||||||
@ -558,8 +558,7 @@ pub mod shmem {
|
|||||||
String::from_utf8_lossy(map_str_bytes)
|
String::from_utf8_lossy(map_str_bytes)
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
let map =
|
let map = MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, map_size) as *mut u8;
|
||||||
MapViewOfFile(handle.clone(), FILE_MAP_ALL_ACCESS, 0, 0, map_size) as *mut u8;
|
|
||||||
if map == ptr::null_mut() {
|
if map == ptr::null_mut() {
|
||||||
return Err(Error::Unknown(format!(
|
return Err(Error::Unknown(format!(
|
||||||
"Cannot map shared memory {}",
|
"Cannot map shared memory {}",
|
||||||
@ -568,9 +567,9 @@ pub mod shmem {
|
|||||||
}
|
}
|
||||||
let mut ret = Self {
|
let mut ret = Self {
|
||||||
shm_str: [0; 20],
|
shm_str: [0; 20],
|
||||||
handle: handle,
|
handle,
|
||||||
map: map,
|
map,
|
||||||
map_size: map_size,
|
map_size,
|
||||||
};
|
};
|
||||||
ret.shm_str.clone_from_slice(&map_str_bytes[0..20]);
|
ret.shm_str.clone_from_slice(&map_str_bytes[0..20]);
|
||||||
Ok(ret)
|
Ok(ret)
|
||||||
|
@ -16,10 +16,14 @@ use crate::utils::{fork, ForkResult};
|
|||||||
|
|
||||||
#[cfg(all(feature = "std", unix))]
|
#[cfg(all(feature = "std", unix))]
|
||||||
use crate::bolts::shmem::UnixShMem;
|
use crate::bolts::shmem::UnixShMem;
|
||||||
|
|
||||||
|
#[cfg(all(feature = "std", unix))]
|
||||||
|
use crate::bolts::shmem::HasFd;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
bolts::{
|
bolts::{
|
||||||
llmp::{self, LlmpClient, LlmpClientDescription, LlmpSender, Tag},
|
llmp::{self, LlmpClient, LlmpClientDescription, LlmpSender, Tag},
|
||||||
shmem::{HasFd, ShMem},
|
shmem::ShMem,
|
||||||
},
|
},
|
||||||
corpus::CorpusScheduler,
|
corpus::CorpusScheduler,
|
||||||
events::{BrokerEventResult, Event, EventManager},
|
events::{BrokerEventResult, Event, EventManager},
|
||||||
@ -304,6 +308,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(all(feature = "std", unix))]
|
||||||
impl<I, S, SH, ST> LlmpEventManager<I, S, SH, ST>
|
impl<I, S, SH, ST> LlmpEventManager<I, S, SH, ST>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
@ -511,7 +516,7 @@ pub fn setup_restarting_mgr<I, S, SH, ST>(
|
|||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
S: DeserializeOwned + IfInteresting<I>,
|
S: DeserializeOwned + IfInteresting<I>,
|
||||||
SH: ShMem + HasFd, // Todo: HasFd is only needed for Android
|
SH: ShMem, // Todo: HasFd is only needed for Android
|
||||||
ST: Stats,
|
ST: Stats,
|
||||||
{
|
{
|
||||||
let mut mgr;
|
let mut mgr;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user