Fixes for no_std build (#214)
* builds on no_std * fixed std build * nightly fmt on CI * nightly fmt on CI (again) * fmt * no_std build on unix * more mem * added no_std from #212 to gh workflow * more ci, less nightly * clippy * more toolchains? * docu * y u no build * more ci? * next try * fixed dockr * more dockerfile fixes * ondisk corpus fixed * panic:? * ubunutu Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com>
This commit is contained in:
parent
badf3f0e6e
commit
0121096e84
25
.github/workflows/build_and_test.yml
vendored
25
.github/workflows/build_and_test.yml
vendored
@ -71,10 +71,32 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
profile: minimal
|
profile: minimal
|
||||||
toolchain: stable
|
toolchain: stable
|
||||||
|
- name: Add nightly rustfmt and clippy
|
||||||
|
run: rustup toolchain install nightly --component rustfmt --component clippy --allow-downgrade
|
||||||
- name: Install deps
|
- name: Install deps
|
||||||
run: sudo apt-get install -y llvm llvm-dev clang nasm
|
run: sudo apt-get install -y llvm llvm-dev clang nasm
|
||||||
- name: Build and run example fuzzers
|
- name: Build and run example fuzzers
|
||||||
run: ./scripts/build_all_fuzzers.sh
|
run: ./scripts/build_all_fuzzers.sh
|
||||||
|
nostd-build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
profile: minimal
|
||||||
|
toolchain: nightly
|
||||||
|
- name: Add nightly rustfmt and clippy
|
||||||
|
run: rustup toolchain install nightly && rustup target add --toolchain nightly aarch64-unknown-none && rustup component add --toolchain nightly rust-src
|
||||||
|
- name: Build aarch64-unknown-none
|
||||||
|
run: cd ./fuzzers/baby_no_std && cargo +nightly build -Zbuild-std=core,alloc --target aarch64-unknown-none -v --release && cd ../..
|
||||||
|
- name: run x86_64 until panic!
|
||||||
|
run: cd ./fuzzers/baby_no_std && cargo +nightly run || test $? -eq 1 || exit 1
|
||||||
|
build-docker:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Build docker
|
||||||
|
run: docker build -t libafl .
|
||||||
windows:
|
windows:
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
steps:
|
steps:
|
||||||
@ -113,9 +135,10 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
profile: minimal
|
profile: minimal
|
||||||
toolchain: stable
|
toolchain: stable
|
||||||
|
- name: Add nightly rustfmt and clippy
|
||||||
|
run: rustup toolchain install nightly --component rustfmt --component clippy --allow-downgrade
|
||||||
- name: Install deps
|
- name: Install deps
|
||||||
run: brew install llvm libpng nasm
|
run: brew install llvm libpng nasm
|
||||||
|
|
||||||
- name: Increase map sizes
|
- name: Increase map sizes
|
||||||
run: ./scripts/shmem_limits_macos.sh
|
run: ./scripts/shmem_limits_macos.sh
|
||||||
- name: Build and run example fuzzers
|
- name: Build and run example fuzzers
|
||||||
|
@ -37,8 +37,14 @@ COPY libafl_frida/Cargo.toml libafl_frida/build.rs libafl_frida/
|
|||||||
COPY scripts/dummy.rs libafl_frida/src/lib.rs
|
COPY scripts/dummy.rs libafl_frida/src/lib.rs
|
||||||
COPY libafl_frida/src/gettls.c libafl_frida/src/gettls.c
|
COPY libafl_frida/src/gettls.c libafl_frida/src/gettls.c
|
||||||
|
|
||||||
|
COPY libafl_qemu/Cargo.toml libafl_qemu/build.rs libafl_qemu/
|
||||||
|
COPY scripts/dummy.rs libafl_qemu/src/lib.rs
|
||||||
|
COPY libafl_qemu/src/weaks.c libafl_qemu/src/weaks.c
|
||||||
|
|
||||||
COPY libafl_cc/Cargo.toml libafl_cc/Cargo.toml
|
COPY libafl_cc/Cargo.toml libafl_cc/Cargo.toml
|
||||||
COPY scripts/dummy.rs libafl_cc/src/lib.rs
|
COPY scripts/dummy.rs libafl_cc/src/lib.rs
|
||||||
|
COPY libafl_cc/build.rs libafl_cc/build.rs
|
||||||
|
COPY libafl_cc/src/cmplog-routines-pass.cc libafl_cc/src/cmplog-routines-pass.cc
|
||||||
|
|
||||||
COPY libafl_targets/Cargo.toml libafl_targets/build.rs libafl_targets/
|
COPY libafl_targets/Cargo.toml libafl_targets/build.rs libafl_targets/
|
||||||
COPY libafl_targets/src libafl_targets/src
|
COPY libafl_targets/src libafl_targets/src
|
||||||
@ -73,6 +79,8 @@ RUN touch libafl/src/lib.rs
|
|||||||
COPY libafl_targets/src libafl_targets/src
|
COPY libafl_targets/src libafl_targets/src
|
||||||
RUN touch libafl_targets/src/lib.rs
|
RUN touch libafl_targets/src/lib.rs
|
||||||
COPY libafl_frida/src libafl_frida/src
|
COPY libafl_frida/src libafl_frida/src
|
||||||
|
RUN touch libafl_qemu/src/lib.rs
|
||||||
|
COPY libafl_qemu/src libafl_qemu/src
|
||||||
RUN touch libafl_frida/src/lib.rs
|
RUN touch libafl_frida/src/lib.rs
|
||||||
RUN cargo build && cargo build --release
|
RUN cargo build && cargo build --release
|
||||||
|
|
||||||
|
@ -5,3 +5,4 @@ This is a minimalistic example about how to create a libafl based fuzzer.
|
|||||||
It runs on a single core until a crash occurs and then exits.
|
It runs on a single core until a crash occurs and then exits.
|
||||||
|
|
||||||
The tested program is a simple Rust function without any instrumentation.
|
The tested program is a simple Rust function without any instrumentation.
|
||||||
|
For real fuzzing, you will want to add some sort to add coverage or other feedback.
|
1
fuzzers/baby_no_std/.gitignore
vendored
Normal file
1
fuzzers/baby_no_std/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
libpng-*
|
24
fuzzers/baby_no_std/Cargo.toml
Normal file
24
fuzzers/baby_no_std/Cargo.toml
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
[package]
|
||||||
|
name = "baby_no_std"
|
||||||
|
version = "0.5.0"
|
||||||
|
authors = ["Andrea Fioraldi <andreafioraldi@gmail.com>", "Dominik Maier <domenukk@gmail.com>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[profile.dev]
|
||||||
|
panic = "abort"
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
panic = "abort"
|
||||||
|
lto = true
|
||||||
|
codegen-units = 1
|
||||||
|
opt-level = 3
|
||||||
|
debug = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
libafl = { default-features = false, path = "../../libafl/" }
|
||||||
|
static-alloc = "0.2.3"
|
||||||
|
|
||||||
|
[target.'cfg(unix)'.dependencies]
|
||||||
|
libc = "0.2"
|
||||||
|
cstr_core = "0.2.3"
|
||||||
|
|
8
fuzzers/baby_no_std/README.md
Normal file
8
fuzzers/baby_no_std/README.md
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# Baby `no_std`
|
||||||
|
|
||||||
|
This is a minimalistic example how to create a libafl based fuzzer that works on `no_std` environments like TEEs, Kernels or on barew metal.
|
||||||
|
|
||||||
|
It runs on a single core until a crash occurs and then calls the panic handler.
|
||||||
|
|
||||||
|
The tested program is a simple Rust function without any instrumentation.
|
||||||
|
For real fuzzing, you will want to add some sort to add coverage or other feedback.
|
141
fuzzers/baby_no_std/src/main.rs
Normal file
141
fuzzers/baby_no_std/src/main.rs
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
#![no_std]
|
||||||
|
// Embedded targets: build with no_main
|
||||||
|
#![cfg_attr(not(any(windows, unix)), no_main)]
|
||||||
|
// Embedded needs alloc error handlers which only work on nightly right now...
|
||||||
|
#![cfg_attr(not(any(windows, unix)), feature(default_alloc_error_handler))]
|
||||||
|
|
||||||
|
use libafl::{
|
||||||
|
bolts::{current_nanos, rands::StdRand, tuples::tuple_list},
|
||||||
|
corpus::{InMemoryCorpus, QueueCorpusScheduler},
|
||||||
|
events::SimpleEventManager,
|
||||||
|
executors::{inprocess::InProcessExecutor, ExitKind},
|
||||||
|
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback},
|
||||||
|
fuzzer::{Fuzzer, StdFuzzer},
|
||||||
|
generators::RandPrintablesGenerator,
|
||||||
|
inputs::{BytesInput, HasTargetBytes},
|
||||||
|
mutators::scheduled::{havoc_mutations, StdScheduledMutator},
|
||||||
|
observers::StdMapObserver,
|
||||||
|
stages::mutational::StdMutationalStage,
|
||||||
|
state::StdState,
|
||||||
|
stats::SimpleStats,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(any(windows, unix))]
|
||||||
|
use cstr_core::CString;
|
||||||
|
#[cfg(any(windows, unix))]
|
||||||
|
use libc::{c_char, printf};
|
||||||
|
|
||||||
|
#[cfg(not(any(windows, unix)))]
|
||||||
|
use core::panic::PanicInfo;
|
||||||
|
use static_alloc::Bump;
|
||||||
|
|
||||||
|
#[global_allocator]
|
||||||
|
static A: Bump<[u8; 512 * 1024 * 1024]> = Bump::uninit();
|
||||||
|
|
||||||
|
#[cfg(not(any(windows, unix)))]
|
||||||
|
#[panic_handler]
|
||||||
|
fn panic(_info: &PanicInfo) -> ! {
|
||||||
|
loop {}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Coverage map with explicit assignments due to the lack of instrumentation
|
||||||
|
static mut SIGNALS: [u8; 16] = [0; 16];
|
||||||
|
|
||||||
|
/// Assign a signal to the signals map
|
||||||
|
fn signals_set(idx: usize) {
|
||||||
|
unsafe { SIGNALS[idx] = 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::similar_names)]
|
||||||
|
pub fn main() {
|
||||||
|
// The closure that we want to fuzz
|
||||||
|
let mut harness = |input: &BytesInput| {
|
||||||
|
let target = input.target_bytes();
|
||||||
|
let buf = target.as_slice();
|
||||||
|
signals_set(0);
|
||||||
|
if !buf.is_empty() && buf[0] == b'a' {
|
||||||
|
signals_set(1);
|
||||||
|
if buf.len() > 1 && buf[1] == b'b' {
|
||||||
|
signals_set(2);
|
||||||
|
if buf.len() > 2 && buf[2] == b'c' {
|
||||||
|
panic!("=)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ExitKind::Ok
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create an observation channel using the signals map
|
||||||
|
let observer = StdMapObserver::new("signals", unsafe { &mut SIGNALS });
|
||||||
|
|
||||||
|
// The state of the edges feedback.
|
||||||
|
let feedback_state = MapFeedbackState::with_observer(&observer);
|
||||||
|
|
||||||
|
// Feedback to rate the interestingness of an input
|
||||||
|
let feedback = MaxMapFeedback::new(&feedback_state, &observer);
|
||||||
|
|
||||||
|
// A feedback to choose if an input is a solution or not
|
||||||
|
let objective = CrashFeedback::new();
|
||||||
|
|
||||||
|
// create a State from scratch
|
||||||
|
let mut state = StdState::new(
|
||||||
|
// RNG
|
||||||
|
StdRand::with_seed(current_nanos()),
|
||||||
|
// Corpus that will be evolved, we keep it in memory for performance
|
||||||
|
InMemoryCorpus::new(),
|
||||||
|
// Corpus in which we store solutions (crashes in this example),
|
||||||
|
// on disk so the user can get them after stopping the fuzzer
|
||||||
|
InMemoryCorpus::new(),
|
||||||
|
// States of the feedbacks.
|
||||||
|
// They are the data related to the feedbacks that you want to persist in the State.
|
||||||
|
tuple_list!(feedback_state),
|
||||||
|
);
|
||||||
|
|
||||||
|
// The Stats trait define how the fuzzer stats are reported to the user
|
||||||
|
let stats = SimpleStats::new(|s| {
|
||||||
|
// TODO: Print `s` here, if your target permits it.
|
||||||
|
#[cfg(any(windows, unix))]
|
||||||
|
unsafe {
|
||||||
|
printf(
|
||||||
|
[b'%' as c_char, b's' as c_char, b'\n' as c_char, 0 as c_char].as_ptr(),
|
||||||
|
CString::new(s).unwrap().as_ptr() as *const c_char,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// The event manager handle the various events generated during the fuzzing loop
|
||||||
|
// such as the notification of the addition of a new item to the corpus
|
||||||
|
let mut mgr = SimpleEventManager::new(stats);
|
||||||
|
|
||||||
|
// A queue policy to get testcasess from the corpus
|
||||||
|
let scheduler = QueueCorpusScheduler::new();
|
||||||
|
|
||||||
|
// A fuzzer with feedbacks and a corpus scheduler
|
||||||
|
let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective);
|
||||||
|
|
||||||
|
// Create the executor for an in-process function with just one observer
|
||||||
|
let mut executor = InProcessExecutor::new(
|
||||||
|
&mut harness,
|
||||||
|
tuple_list!(observer),
|
||||||
|
&mut fuzzer,
|
||||||
|
&mut state,
|
||||||
|
&mut mgr,
|
||||||
|
)
|
||||||
|
.expect("Failed to create the Executor");
|
||||||
|
|
||||||
|
// Generator of printable bytearrays of max size 32
|
||||||
|
let mut generator = RandPrintablesGenerator::new(32);
|
||||||
|
|
||||||
|
// Generate 8 initial inputs
|
||||||
|
state
|
||||||
|
.generate_initial_inputs(&mut fuzzer, &mut executor, &mut generator, &mut mgr, 8)
|
||||||
|
.expect("Failed to generate the initial corpus");
|
||||||
|
|
||||||
|
// Setup a mutational stage with a basic bytes mutator
|
||||||
|
let mutator = StdScheduledMutator::new(havoc_mutations());
|
||||||
|
let mut stages = tuple_list!(StdMutationalStage::new(mutator));
|
||||||
|
|
||||||
|
fuzzer
|
||||||
|
.fuzz_loop(&mut stages, &mut executor, &mut state, &mut mgr)
|
||||||
|
.expect("Error in the fuzzing loop");
|
||||||
|
}
|
@ -37,7 +37,7 @@ harness = false
|
|||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["std", "anymap_debug", "derive", "llmp_compression"]
|
default = ["std", "anymap_debug", "derive", "llmp_compression"]
|
||||||
std = ["serde_json"] # print, env, launcher ... support
|
std = ["serde_json", "hostname", "core_affinity", "nix", "serde/std"] # print, env, launcher ... support
|
||||||
anymap_debug = ["serde_json"] # uses serde_json to Debug the anymap trait. Disable for smaller footprint.
|
anymap_debug = ["serde_json"] # uses serde_json to Debug the anymap trait. Disable for smaller footprint.
|
||||||
derive = ["libafl_derive"] # provide derive(SerdeAny) macro.
|
derive = ["libafl_derive"] # provide derive(SerdeAny) macro.
|
||||||
rand_trait = ["rand_core"] # If set, libafl's rand implementations will implement `rand::Rng`
|
rand_trait = ["rand_core"] # If set, libafl's rand implementations will implement `rand::Rng`
|
||||||
@ -53,25 +53,27 @@ path = "./examples/llmp_test/main.rs"
|
|||||||
required-features = ["std"]
|
required-features = ["std"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libafl_derive = { optional = true, path = "../libafl_derive", version = "0.5.0" }
|
tuple_list = { version = "0.1.2", git = "https://github.com/domenukk/tuple_list" }
|
||||||
tuple_list = "0.1.2"
|
hashbrown = { version = "0.9", features = ["serde", "ahash-compile-time-rng"], default-features=false } # A faster hashmap, nostd compatible
|
||||||
hashbrown = { version = "0.9", features = ["serde", "ahash-compile-time-rng"] } # A faster hashmap, nostd compatible
|
num = { version = "0.4.0", default-features = false }
|
||||||
num = "0.4.0"
|
|
||||||
xxhash-rust = { version = "0.8.2", features = ["xxh3"] } # xxh3 hashing for rust
|
xxhash-rust = { version = "0.8.2", features = ["xxh3"] } # xxh3 hashing for rust
|
||||||
serde = { version = "1.0", default-features = false, features = ["alloc"] } # serialization lib
|
serde = { version = "1.0", default-features = false, features = ["alloc"] } # serialization lib
|
||||||
erased-serde = "0.3.12"
|
erased-serde = { version = "0.3.12", default-features = false, features = ["alloc"] } # erased serde
|
||||||
postcard = { version = "0.5.1", features = ["alloc"] } # no_std compatible serde serialization fromat
|
postcard = { version = "0.5.1", features = ["alloc"] } # no_std compatible serde serialization fromat
|
||||||
static_assertions = "1.1.0"
|
static_assertions = "1.1.0"
|
||||||
ctor = "0.1.20"
|
ctor = "0.1.20"
|
||||||
|
num_enum = { version = "0.5.1", default-features = false }
|
||||||
|
typed-builder = "0.9.0" # Implement the builder pattern at compiletime
|
||||||
|
ahash = { version = "0.7", default-features=false, features=["compile-time-rng"] } # The hash function already used in hashbrown
|
||||||
|
|
||||||
|
libafl_derive = { version = "0.5.0", optional = true, path = "../libafl_derive" }
|
||||||
serde_json = { version = "1.0", optional = true, default-features = false, features = ["alloc"] } # an easy way to debug print SerdeAnyMap
|
serde_json = { version = "1.0", optional = true, default-features = false, features = ["alloc"] } # an easy way to debug print SerdeAnyMap
|
||||||
miniz_oxide = { version = "0.4.4", optional = true}
|
miniz_oxide = { version = "0.4.4", optional = true}
|
||||||
core_affinity = { version = "0.5", git = "https://github.com/s1341/core_affinity_rs" }
|
core_affinity = { version = "0.5", git = "https://github.com/s1341/core_affinity_rs", optional = true }
|
||||||
num_enum = "0.5.1" # compression/decomrpession lib
|
hostname = { version = "^0.3", optional = true } # Is there really no gethostname in the stdlib?
|
||||||
hostname = "^0.3" # Is there really no gethostname in the stdlib?
|
|
||||||
typed-builder = "0.9.0" # Implement the builder pattern at compiletime
|
|
||||||
ahash ="0.7" # The hash function already used in hashbrown
|
|
||||||
rand = { version = "0.8.1", optional = true } #
|
rand = { version = "0.8.1", optional = true } #
|
||||||
rand_core = { version = "0.6.2", optional = true } # This dependency allows us to export our RomuRand as rand::Rng.
|
rand_core = { version = "0.6.2", optional = true } # This dependency allows us to export our RomuRand as rand::Rng.
|
||||||
|
nix = { version = "0.20.0", optional = true }
|
||||||
|
|
||||||
[target.'cfg(target_os = "android")'.dependencies]
|
[target.'cfg(target_os = "android")'.dependencies]
|
||||||
backtrace = { version = "0.3", optional = true, default-features = false, features = ["std", "libbacktrace"] } # for llmp_debug
|
backtrace = { version = "0.3", optional = true, default-features = false, features = ["std", "libbacktrace"] } # for llmp_debug
|
||||||
@ -81,7 +83,6 @@ backtrace = { version = "0.3", optional = true } # for llmp_debug
|
|||||||
|
|
||||||
[target.'cfg(unix)'.dependencies]
|
[target.'cfg(unix)'.dependencies]
|
||||||
libc = "0.2" # For (*nix) libc
|
libc = "0.2" # For (*nix) libc
|
||||||
nix = "0.20.0"
|
|
||||||
uds = "0.2.3"
|
uds = "0.2.3"
|
||||||
lock_api = "0.4.3"
|
lock_api = "0.4.3"
|
||||||
regex = "1.4.5"
|
regex = "1.4.5"
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
//! Operating System specific abstractions
|
//! Operating System specific abstractions
|
||||||
|
|
||||||
use alloc::vec::Vec;
|
|
||||||
|
|
||||||
#[cfg(any(unix, all(windows, feature = "std")))]
|
#[cfg(any(unix, all(windows, feature = "std")))]
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
|
||||||
@ -14,7 +12,7 @@ pub mod ashmem_server;
|
|||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
pub mod unix_signals;
|
pub mod unix_signals;
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(all(unix, feature = "std"))]
|
||||||
pub mod pipes;
|
pub mod pipes;
|
||||||
|
|
||||||
#[cfg(all(unix, feature = "std"))]
|
#[cfg(all(unix, feature = "std"))]
|
||||||
@ -101,6 +99,7 @@ pub fn dup2(fd: i32, device: i32) -> Result<(), Error> {
|
|||||||
/// `./fuzzer --cores 1,2-4,6` -> clients run in cores 1,2,3,4,6
|
/// `./fuzzer --cores 1,2-4,6` -> clients run in cores 1,2,3,4,6
|
||||||
/// ` ./fuzzer --cores all` -> one client runs on each available core
|
/// ` ./fuzzer --cores all` -> one client runs on each available core
|
||||||
#[must_use]
|
#[must_use]
|
||||||
|
#[cfg(feature = "std")]
|
||||||
pub fn parse_core_bind_arg(args: &str) -> Option<Vec<usize>> {
|
pub fn parse_core_bind_arg(args: &str) -> Option<Vec<usize>> {
|
||||||
let mut cores: Vec<usize> = vec![];
|
let mut cores: Vec<usize> = vec![];
|
||||||
if args == "all" {
|
if args == "all" {
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
//! Unix `pipe` wrapper for `LibAFL`
|
//! Unix `pipe` wrapper for `LibAFL`
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
use nix::unistd::{close, pipe};
|
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use nix::unistd::{read, write};
|
use nix::unistd::{close, pipe, read, write};
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use std::{
|
use std::{
|
||||||
io::{self, ErrorKind, Read, Write},
|
io::{self, ErrorKind, Read, Write},
|
||||||
@ -13,12 +11,14 @@ use std::{
|
|||||||
#[cfg(not(feature = "std"))]
|
#[cfg(not(feature = "std"))]
|
||||||
type RawFd = i32;
|
type RawFd = i32;
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Pipe {
|
pub struct Pipe {
|
||||||
read_end: Option<RawFd>,
|
read_end: Option<RawFd>,
|
||||||
write_end: Option<RawFd>,
|
write_end: Option<RawFd>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
impl Pipe {
|
impl Pipe {
|
||||||
pub fn new() -> Result<Self, Error> {
|
pub fn new() -> Result<Self, Error> {
|
||||||
let (read_end, write_end) = pipe()?;
|
let (read_end, write_end) = pipe()?;
|
||||||
@ -91,6 +91,7 @@ impl Write for Pipe {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
impl Drop for Pipe {
|
impl Drop for Pipe {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if let Some(read_end) = self.read_end {
|
if let Some(read_end) = self.read_end {
|
||||||
|
@ -3,9 +3,10 @@
|
|||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use core::cell::RefCell;
|
use core::cell::RefCell;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use std::{fs, fs::File, io::Write, path::PathBuf};
|
use std::{fs, fs::File, io::Write};
|
||||||
|
|
||||||
use crate::{corpus::Corpus, corpus::Testcase, inputs::Input, state::HasMetadata, Error};
|
use crate::{corpus::Corpus, corpus::Testcase, inputs::Input, state::HasMetadata, Error};
|
||||||
|
|
||||||
@ -128,7 +129,7 @@ where
|
|||||||
Ok(Self {
|
Ok(Self {
|
||||||
entries: vec![],
|
entries: vec![],
|
||||||
current: None,
|
current: None,
|
||||||
dir_path,
|
dir_path: dir_path,
|
||||||
meta_format: None,
|
meta_format: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -143,7 +144,7 @@ where
|
|||||||
Ok(Self {
|
Ok(Self {
|
||||||
entries: vec![],
|
entries: vec![],
|
||||||
current: None,
|
current: None,
|
||||||
dir_path,
|
dir_path: dir_path,
|
||||||
meta_format,
|
meta_format,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -5,9 +5,11 @@ use alloc::{
|
|||||||
vec::Vec,
|
vec::Vec,
|
||||||
};
|
};
|
||||||
use core::{marker::PhantomData, time::Duration};
|
use core::{marker::PhantomData, time::Duration};
|
||||||
use core_affinity::CoreId;
|
|
||||||
use serde::{de::DeserializeOwned, Serialize};
|
use serde::{de::DeserializeOwned, Serialize};
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
use core_affinity::CoreId;
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use core::ptr::{addr_of, read_volatile};
|
use core::ptr::{addr_of, read_volatile};
|
||||||
|
|
||||||
@ -689,6 +691,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The kind of manager we're creating right now
|
/// The kind of manager we're creating right now
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum ManagerKind {
|
pub enum ManagerKind {
|
||||||
/// Any kind will do
|
/// Any kind will do
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
//! The [`InProcessExecutor`] is a libfuzzer-like executor, that will simply call a function.
|
//! The [`InProcessExecutor`] is a libfuzzer-like executor, that will simply call a function.
|
||||||
//! It should usually be paired with extra error-handling, such as a restarting event manager, to be effective.
|
//! It should usually be paired with extra error-handling, such as a restarting event manager, to be effective.
|
||||||
|
|
||||||
use core::marker::PhantomData;
|
use core::{ffi::c_void, marker::PhantomData, ptr};
|
||||||
|
|
||||||
#[cfg(any(unix, all(windows, feature = "std")))]
|
#[cfg(any(unix, all(windows, feature = "std")))]
|
||||||
use core::{
|
use core::{
|
||||||
ffi::c_void,
|
ptr::write_volatile,
|
||||||
ptr::{self, write_volatile},
|
|
||||||
sync::atomic::{compiler_fence, Ordering},
|
sync::atomic::{compiler_fence, Ordering},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -28,6 +27,8 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// The inmem executor simply calls a target function, then returns afterwards.
|
/// The inmem executor simply calls a target function, then returns afterwards.
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct InProcessExecutor<'a, H, I, OT, S>
|
pub struct InProcessExecutor<'a, H, I, OT, S>
|
||||||
where
|
where
|
||||||
H: FnMut(&I) -> ExitKind,
|
H: FnMut(&I) -> ExitKind,
|
||||||
@ -54,9 +55,9 @@ where
|
|||||||
#[inline]
|
#[inline]
|
||||||
fn run_target(
|
fn run_target(
|
||||||
&mut self,
|
&mut self,
|
||||||
fuzzer: &mut Z,
|
_fuzzer: &mut Z,
|
||||||
state: &mut S,
|
_state: &mut S,
|
||||||
mgr: &mut EM,
|
_mgr: &mut EM,
|
||||||
input: &I,
|
input: &I,
|
||||||
) -> Result<ExitKind, Error> {
|
) -> Result<ExitKind, Error> {
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
@ -74,9 +75,9 @@ where
|
|||||||
data.timeout_handler = self.timeout_handler;
|
data.timeout_handler = self.timeout_handler;
|
||||||
// Direct raw pointers access /aliasing is pretty undefined behavior.
|
// Direct raw pointers access /aliasing is pretty undefined behavior.
|
||||||
// Since the state and event may have moved in memory, refresh them right before the signal may happen
|
// Since the state and event may have moved in memory, refresh them right before the signal may happen
|
||||||
write_volatile(&mut data.state_ptr, state as *mut _ as *mut c_void);
|
write_volatile(&mut data.state_ptr, _state as *mut _ as *mut c_void);
|
||||||
write_volatile(&mut data.event_mgr_ptr, mgr as *mut _ as *mut c_void);
|
write_volatile(&mut data.event_mgr_ptr, _mgr as *mut _ as *mut c_void);
|
||||||
write_volatile(&mut data.fuzzer_ptr, fuzzer as *mut _ as *mut c_void);
|
write_volatile(&mut data.fuzzer_ptr, _fuzzer as *mut _ as *mut c_void);
|
||||||
compiler_fence(Ordering::SeqCst);
|
compiler_fence(Ordering::SeqCst);
|
||||||
}
|
}
|
||||||
#[cfg(all(windows, feature = "std"))]
|
#[cfg(all(windows, feature = "std"))]
|
||||||
@ -94,9 +95,9 @@ where
|
|||||||
//data.timeout_handler = self.timeout_handler;
|
//data.timeout_handler = self.timeout_handler;
|
||||||
// Direct raw pointers access /aliasing is pretty undefined behavior.
|
// Direct raw pointers access /aliasing is pretty undefined behavior.
|
||||||
// Since the state and event may have moved in memory, refresh them right before the signal may happen
|
// Since the state and event may have moved in memory, refresh them right before the signal may happen
|
||||||
write_volatile(&mut data.state_ptr, state as *mut _ as *mut c_void);
|
write_volatile(&mut data.state_ptr, _state as *mut _ as *mut c_void);
|
||||||
write_volatile(&mut data.event_mgr_ptr, mgr as *mut _ as *mut c_void);
|
write_volatile(&mut data.event_mgr_ptr, _mgr as *mut _ as *mut c_void);
|
||||||
write_volatile(&mut data.fuzzer_ptr, fuzzer as *mut _ as *mut c_void);
|
write_volatile(&mut data.fuzzer_ptr, _fuzzer as *mut _ as *mut c_void);
|
||||||
compiler_fence(Ordering::SeqCst);
|
compiler_fence(Ordering::SeqCst);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,6 +211,8 @@ where
|
|||||||
Ok(Self {
|
Ok(Self {
|
||||||
harness_fn,
|
harness_fn,
|
||||||
observers,
|
observers,
|
||||||
|
crash_handler: ptr::null(),
|
||||||
|
timeout_handler: ptr::null(),
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
//! A `TimeoutExecutor` sets a timeout before each target run
|
//! A `TimeoutExecutor` sets a timeout before each target run
|
||||||
|
|
||||||
|
#[cfg(any(windows, unix))]
|
||||||
use core::time::Duration;
|
use core::time::Duration;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -332,7 +332,7 @@ where
|
|||||||
#[cfg(not(feature = "introspection"))]
|
#[cfg(not(feature = "introspection"))]
|
||||||
let is_solution = self
|
let is_solution = self
|
||||||
.objective_mut()
|
.objective_mut()
|
||||||
.is_interesting(state, manager, &input, observers, &exit_kind)?;
|
.is_interesting(state, manager, &input, observers, exit_kind)?;
|
||||||
|
|
||||||
#[cfg(feature = "introspection")]
|
#[cfg(feature = "introspection")]
|
||||||
let is_solution = self
|
let is_solution = self
|
||||||
@ -345,7 +345,7 @@ where
|
|||||||
#[cfg(not(feature = "introspection"))]
|
#[cfg(not(feature = "introspection"))]
|
||||||
let is_corpus = self
|
let is_corpus = self
|
||||||
.feedback_mut()
|
.feedback_mut()
|
||||||
.is_interesting(state, manager, &input, observers, &exit_kind)?;
|
.is_interesting(state, manager, &input, observers, exit_kind)?;
|
||||||
|
|
||||||
#[cfg(feature = "introspection")]
|
#[cfg(feature = "introspection")]
|
||||||
let is_corpus = self
|
let is_corpus = self
|
||||||
|
@ -45,6 +45,9 @@ use core::fmt;
|
|||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use std::{env::VarError, io, num::ParseIntError, string::FromUtf8Error};
|
use std::{env::VarError, io, num::ParseIntError, string::FromUtf8Error};
|
||||||
|
|
||||||
|
#[cfg(all(unix, feature = "std"))]
|
||||||
|
use nix;
|
||||||
|
|
||||||
/// Main error struct for AFL
|
/// Main error struct for AFL
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
@ -120,7 +123,7 @@ impl From<serde_json::Error> for Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(all(unix, feature = "std"))]
|
||||||
impl From<nix::Error> for Error {
|
impl From<nix::Error> for Error {
|
||||||
fn from(err: nix::Error) -> Self {
|
fn from(err: nix::Error) -> Self {
|
||||||
Self::Unknown(format!("{:?}", err))
|
Self::Unknown(format!("{:?}", err))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user