From fe51286586c35fd5d2fe8eeed39f1f5489421651 Mon Sep 17 00:00:00 2001 From: "Dongjia \"toka\" Zhang" Date: Mon, 23 Jan 2023 19:11:53 +0900 Subject: [PATCH] TinyInst Update (#968) * tmp * more * save * TODO * fix * update to tinyinst on crates * dep * fmt * shmem done * cpp fmt * clp * fmt * why?? * ver * more makefile.toml * windows test * Update build_and_test.yml * fix * a * install * fmt * fix * only macos and win * more * The order matters * remove * fmt * chg * typo Co-authored-by: Andrea Fioraldi --- .github/workflows/build_and_test.yml | 9 + fuzzers/tinyinst_simple/Cargo.toml | 4 +- fuzzers/tinyinst_simple/Makefile.toml | 56 +++++- fuzzers/tinyinst_simple/README.md | 10 +- fuzzers/tinyinst_simple/src/main.rs | 38 +++- fuzzers/tinyinst_simple/test/test.c | 36 ---- fuzzers/tinyinst_simple/test/test.cpp | 163 ++++++++++++++++ libafl/src/events/simple.rs | 2 +- libafl/src/executors/forkserver.rs | 2 +- libafl_tinyinst/Cargo.toml | 2 +- libafl_tinyinst/README.md | 5 +- libafl_tinyinst/src/executor.rs | 262 ++++++++++++++++++++++---- libafl_tinyinst/src/lib.rs | 68 +++++++ 13 files changed, 562 insertions(+), 95 deletions(-) delete mode 100644 fuzzers/tinyinst_simple/test/test.c create mode 100644 fuzzers/tinyinst_simple/test/test.cpp diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index ec03ad119f..cbca4ae41e 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -173,6 +173,9 @@ jobs: run: rustup toolchain install nightly --component rustfmt --component clippy --allow-downgrade - name: Add no_std toolchain run: rustup toolchain install nightly-x86_64-unknown-linux-gnu ; rustup component add rust-src --toolchain nightly-x86_64-unknown-linux-gnu + - name: Install cxxbridge + if: runner.os == 'macOS' + run: cargo install cxxbridge-cmd - name: Install python (macOS) # Removing macOS things already installed in CI against failed linking if: runner.os == 'macOS' @@ -255,10 +258,14 @@ jobs: - name: install cargo-make run: cargo install --force cargo-make - uses: ilammy/msvc-dev-cmd@v1 + - name: install cxx bridge + run: cargo install cxxbridge-cmd - name: Build fuzzers/frida_libpng run: cd fuzzers/frida_libpng/ && cargo make test - name: Build fuzzers/frida_gdiplus run: cd fuzzers/frida_gdiplus/ && cargo make test + - name: Build fuzzers/tinyinst_simple + run: cd fuzzers/tinyinst_simple/ && cargo make test macos: runs-on: macOS-latest @@ -271,6 +278,8 @@ jobs: run: rustup toolchain install nightly --component rustfmt --component clippy --allow-downgrade - name: Install deps run: brew install z3 gtk+3 + - name: Install cxxbridge + run: cargo install cxxbridge-cmd - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v2 - name: MacOS Build diff --git a/fuzzers/tinyinst_simple/Cargo.toml b/fuzzers/tinyinst_simple/Cargo.toml index 6183b66259..cdf6972fae 100644 --- a/fuzzers/tinyinst_simple/Cargo.toml +++ b/fuzzers/tinyinst_simple/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -libafl = { version = "0.8.1", path = "../../libafl", features = ["tui"] } -libafl_tinyinst = { version = "0.8.1", path = "../../libafl_tinyinst" } +libafl = { version = "0.8.2", path = "../../libafl", features = ["introspection"] } +libafl_tinyinst = { version = "0.8.2", path = "../../libafl_tinyinst" } [profile.release] codegen-units = 1 opt-level = 3 diff --git a/fuzzers/tinyinst_simple/Makefile.toml b/fuzzers/tinyinst_simple/Makefile.toml index 896481cf05..a43580c8ea 100644 --- a/fuzzers/tinyinst_simple/Makefile.toml +++ b/fuzzers/tinyinst_simple/Makefile.toml @@ -1,8 +1,56 @@ -[tasks.build_test] -command = "cl" -args = ["./test/test.c", "-o", "./test/test.exe"] +[tasks.unsupported] +script_runner="@shell" +script=''' +echo "Cargo-make not integrated yet on this" +''' +# Harness +[tasks.harness] +linux_alias = "unsupported" +mac_alias = "unsupported" +windows_alias = "harness_windows" + +[tasks.harness_windows] +script=''' +cl test\test.cpp -o test.exe +''' + +# Fuzzer +[tasks.fuzzer] +linux_alias = "unsupported" +mac_alias = "unsupported" +windows_alias = "fuzzer_windows" + +[tasks.fuzzer_windows] +dependencies = ["harness"] +command = "cargo" +args = ["build", "--release"] + +# Run the fuzzer [tasks.run] -dependencies = ["build_test"] +linux_alias = "unsupported" +mac_alias = "unsupported" +windows_alias = "run_windows" + +[tasks.run_windows] +dependencies = ["harness", "fuzzer"] command = "cargo" args = ["run", "--release"] + + +# Run the fuzzer +[tasks.test] +linux_alias = "unsupported" +mac_alias = "unsupported" +windows_alias = "test_windows" + +[tasks.test_windows] +script_runner = "@shell" +script=''' +copy .\target\release\tinyinst_simple.exe . +start "" "tinyinst_simple.exe" +#ping is for timeout +ping -n 10 127.0.0.1>NUL && taskkill /im tinyinst_simple.exe /F +>nul 2>nul dir /a-d "corpus_discovered\*" && (echo Files exist) || (exit /b 1337) +''' +dependencies = [ "harness", "fuzzer" ] \ No newline at end of file diff --git a/fuzzers/tinyinst_simple/README.md b/fuzzers/tinyinst_simple/README.md index 3d99aa2178..d20943d3e6 100644 --- a/fuzzers/tinyinst_simple/README.md +++ b/fuzzers/tinyinst_simple/README.md @@ -1,3 +1,11 @@ -# Run Instruction +# Tinyinst example +This is a fuzzer example to show how libafl_tinyinst works + +## How to build +1. Build the harness with `cl test\test.cpp -o test.exe` +2. Build the fuzzer with `cargo build --release`. The fuzzer is `target\release\tinyinst_simple.exe` + +## Run with cargo-make +Or, you can simple run it using cargo-make 1. Open up developer powershell so that you have access to cl (Windows Default Compiler) 2. Run `cargo make run` to run the fuzzer \ No newline at end of file diff --git a/fuzzers/tinyinst_simple/src/main.rs b/fuzzers/tinyinst_simple/src/main.rs index 1cae9a5346..d588b9ad01 100644 --- a/fuzzers/tinyinst_simple/src/main.rs +++ b/fuzzers/tinyinst_simple/src/main.rs @@ -1,8 +1,13 @@ use std::path::PathBuf; +#[cfg(target_vendor = "apple")] +use libafl::bolts::shmem::UnixShMemProvider; +#[cfg(windows)] +use libafl::bolts::shmem::Win32ShMemProvider; use libafl::{ bolts::{ rands::{RandomSeed, StdRand}, + shmem::ShMemProvider, tuples::tuple_list, }, corpus::{CachedOnDiskCorpus, Corpus, OnDiskCorpus, Testcase}, @@ -17,17 +22,30 @@ use libafl::{ state::StdState, Fuzzer, StdFuzzer, }; -use libafl_tinyinst::executor::TinyInstExecutor; +use libafl_tinyinst::executor::TinyInstExecutorBuilder; static mut COVERAGE: Vec = vec![]; +#[cfg(not(any(target_vendor = "apple", windows)))] +fn main() {} + +#[cfg(any(target_vendor = "apple", windows))] fn main() { // Tinyinst things let tinyinst_args = vec!["-instrument_module".to_string(), "test.exe".to_string()]; - let args = vec![".\\test\\test.exe".to_string(), "@@".to_string()]; + // use shmem to pass testcases + let args = vec!["test.exe".to_string(), "-m".to_string(), "@@".to_string()]; + + // use file to pass testcases + // let args = vec!["test.exe".to_string(), "-f".to_string(), "@@".to_string()]; let observer = unsafe { ListObserver::new("cov", &mut COVERAGE) }; let mut feedback = ListFeedback::with_observer(&observer); + #[cfg(windows)] + let mut shmem_provider = Win32ShMemProvider::new().unwrap(); + + #[cfg(target_vendor = "apple")] + let mut shmem_provider = UnixShMemProvider::new().unwrap(); let input = BytesInput::new(b"bad".to_vec()); let rand = StdRand::new(); @@ -46,13 +64,15 @@ fn main() { let mut mgr = SimpleEventManager::new(monitor); let mut executor = unsafe { - TinyInstExecutor::new( - &mut COVERAGE, - tinyinst_args, - args, - 5000, - tuple_list!(observer), - ) + TinyInstExecutorBuilder::new() + .tinyinst_args(tinyinst_args) + .program_args(args) + .use_shmem() + .persistent("test.exe".to_string(), "fuzz".to_string(), 1, 10000) + .timeout(std::time::Duration::new(5, 0)) + .shmem_provider(&mut shmem_provider) + .build(&mut COVERAGE, tuple_list!(observer)) + .unwrap() }; let mutator = StdScheduledMutator::new(havoc_mutations()); let mut stages = tuple_list!(StdMutationalStage::new(mutator)); diff --git a/fuzzers/tinyinst_simple/test/test.c b/fuzzers/tinyinst_simple/test/test.c deleted file mode 100644 index 2f2911e626..0000000000 --- a/fuzzers/tinyinst_simple/test/test.c +++ /dev/null @@ -1,36 +0,0 @@ -#include - -void pass1(char *buf, int buf_size) { - char target[0x10]; - if (buf[0] == 'b') { - if (buf[1] == 'a') { - if (buf[2] == 'd') { - if (buf[3] == '1') { - if (buf[4] == '2') { - printf("You got me\n"); - memcpy(target, buf, 0x1000000); - printf("GG\n"); - } - } - } - } - } -} -int main(int argc, char *argv[]) { - FILE *fp; - char buf[0x1000]; - if (argc == 2) { - fp = fopen(argv[1], "r"); - if (fp == NULL) { - printf("File not found\n"); - printf("Received filename %s\n", argv[1]); - return 1; - } - fscanf(fp, "%s", buf); - - pass1(buf, sizeof(buf)); - - } else { - printf("there is nothing\n"); - } -} diff --git a/fuzzers/tinyinst_simple/test/test.cpp b/fuzzers/tinyinst_simple/test/test.cpp new file mode 100644 index 0000000000..9363d9f294 --- /dev/null +++ b/fuzzers/tinyinst_simple/test/test.cpp @@ -0,0 +1,163 @@ +/* +Copyright 2020 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#define _CRT_SECURE_NO_WARNINGS + +#include +#include +#include +#include +#include + +// shared memory stuff + +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) + #include +#else + #include +#endif + +#define MAX_SAMPLE_SIZE 1000000 +#define SHM_SIZE (4 + MAX_SAMPLE_SIZE) +unsigned char *shm_data; + +bool use_shared_memory; + +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) + +int setup_shmem(const char *name) { + HANDLE map_file; + + map_file = OpenFileMapping(FILE_MAP_ALL_ACCESS, // read/write access + FALSE, // do not inherit the name + name); // name of mapping object + + if (map_file == NULL) { + printf("Error accessing shared memory\n"); + return 0; + } + + shm_data = (unsigned char *)MapViewOfFile( + map_file, // handle to map object + FILE_MAP_ALL_ACCESS, // read/write permission + 0, 0, SHM_SIZE); + + if (shm_data == NULL) { + printf("Error accessing shared memory\n"); + return 0; + } + + return 1; +} + +#else + +int setup_shmem(const char *name) { + int fd; + + // get shared memory file descriptor (NOT a file) + fd = shm_open(name, O_RDONLY, S_IRUSR | S_IWUSR); + if (fd == -1) { + printf("Error in shm_open\n"); + return 0; + } + + // map shared memory to process address space + shm_data = + (unsigned char *)mmap(NULL, SHM_SIZE, PROT_READ, MAP_SHARED, fd, 0); + if (shm_data == MAP_FAILED) { + printf("Error in mmap\n"); + return 0; + } + + return 1; +} + +#endif + +// used to force a crash +char *crash = NULL; + +// ensure we can find the target + +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) + #define FUZZ_TARGET_MODIFIERS __declspec(dllexport) +#else + #define FUZZ_TARGET_MODIFIERS __attribute__((noinline)) +#endif + +// actual target function + +void FUZZ_TARGET_MODIFIERS fuzz(char *name) { + char *sample_bytes = NULL; + uint32_t sample_size = 0; + + // read the sample either from file or + // shared memory + if (use_shared_memory) { + sample_size = *(uint32_t *)(shm_data); + if (sample_size > MAX_SAMPLE_SIZE) sample_size = MAX_SAMPLE_SIZE; + sample_bytes = (char *)malloc(sample_size); + memcpy(sample_bytes, shm_data + sizeof(uint32_t), sample_size); + } else { + FILE *fp = fopen(name, "rb"); + if (!fp) { + printf("Error opening %s a\n", name); + return; + } + fseek(fp, 0, SEEK_END); + sample_size = ftell(fp); + fseek(fp, 0, SEEK_SET); + sample_bytes = (char *)malloc(sample_size); + fread(sample_bytes, 1, sample_size, fp); + fclose(fp); + } + // printf("sample_bytes: %s", sample_bytes); + if (sample_size >= 4) { + // check if the sample spells "test" + if (*(uint32_t *)(sample_bytes) == 0x74736574) { + // if so, crash + crash[0] = 1; + } + } + + if (sample_bytes) free(sample_bytes); +} + +int main(int argc, char **argv) { + if (argc != 3) { + printf("Usage: %s <-f|-m> \n", argv[0]); + return 0; + } + if (!strcmp(argv[1], "-m")) { + use_shared_memory = true; + } else if (!strcmp(argv[1], "-f")) { + use_shared_memory = false; + } else { + printf("Usage: %s <-f|-m> \n", argv[0]); + return 0; + } + + // map shared memory here as we don't want to do it + // for every operation + if (use_shared_memory) { + if (!setup_shmem(argv[2])) { printf("Error mapping shared memory\n"); } + } + + fuzz(argv[2]); + + return 0; +} diff --git a/libafl/src/events/simple.rs b/libafl/src/events/simple.rs index 43c4ad5880..87dc591711 100644 --- a/libafl/src/events/simple.rs +++ b/libafl/src/events/simple.rs @@ -254,7 +254,7 @@ where phantom: _, } => { // TODO: The monitor buffer should be added on client add. - let client = &mut monitor.client_stats_mut()[0]; + let client = monitor.client_stats_mut_for(0); client.update_executions(*executions as u64, *time); client.update_introspection_monitor((**introspection_monitor).clone()); monitor.display(event.name().to_string(), 0); diff --git a/libafl/src/executors/forkserver.rs b/libafl/src/executors/forkserver.rs index 1c1eb63550..496b126557 100644 --- a/libafl/src/executors/forkserver.rs +++ b/libafl/src/executors/forkserver.rs @@ -537,7 +537,7 @@ where .field("target", &self.target) .field("args", &self.args) .field("input_file", &self.input_file) - .field("use_shmem_testcase", &self.uses_shmem_testcase) + .field("uses_shmem_testcase", &self.uses_shmem_testcase) .field("forkserver", &self.forkserver) .field("observers", &self.observers) .field("map", &self.map) diff --git a/libafl_tinyinst/Cargo.toml b/libafl_tinyinst/Cargo.toml index ba36f9e7ca..225f00dac2 100644 --- a/libafl_tinyinst/Cargo.toml +++ b/libafl_tinyinst/Cargo.toml @@ -17,7 +17,7 @@ libafl = { path = "../libafl", version = "0.8.0", features = [ "std", "libafl_derive", ] } -tinyinst-rs = { git = "https://github.com/elbiazo/tinyinst-rs" } +tinyinst = { git = "https://github.com/AFLplusplus/tinyinst-rs" } # tinyinst-rs = { path = "../../tinyinst-rs" } [build-dependencies] diff --git a/libafl_tinyinst/README.md b/libafl_tinyinst/README.md index 4bcda1d13c..649e1da19c 100644 --- a/libafl_tinyinst/README.md +++ b/libafl_tinyinst/README.md @@ -1,3 +1,4 @@ # Requirements -- you need `Visual Studio 17 2022`, though it's not tested, it should work on older versions. -- you need `cxxbridge-cmd` to generate bridge files between Rust and c++, you can install this via `cargo install cxxbridge-cmd` \ No newline at end of file +- `Visual Studio 17 2022`. It's not tested, it *should* work on older versions too. +- `cxxbridge-cmd` to generate bridge files between Rust and c++, you can install this with `cargo install cxxbridge-cmd`. +- `cmake` is needed to build tinyinst. \ No newline at end of file diff --git a/libafl_tinyinst/src/executor.rs b/libafl_tinyinst/src/executor.rs index 3f22aea231..f7d16229d7 100644 --- a/libafl_tinyinst/src/executor.rs +++ b/libafl_tinyinst/src/executor.rs @@ -1,27 +1,38 @@ use core::marker::PhantomData; +use std::time::Duration; use libafl::{ - bolts::fs::{InputFile, INPUTFILE_STD}, + bolts::{ + fs::{InputFile, INPUTFILE_STD}, + shmem::{ShMem, ShMemProvider, StdShMemProvider}, + AsMutSlice, AsSlice, + }, executors::{Executor, ExitKind, HasObservers}, inputs::{HasTargetBytes, UsesInput}, observers::{ObserversTuple, UsesObservers}, - prelude::AsSlice, state::{State, UsesState}, Error, }; -use tinyinst_rs::tinyinst::{litecov::RunResult, TinyInst}; +use tinyinst::tinyinst::{litecov::RunResult, TinyInst}; -pub struct TinyInstExecutor<'a, S, OT> { +/// Tinyinst executor +pub struct TinyInstExecutor<'a, S, SP, OT> +where + SP: ShMemProvider, +{ tinyinst: TinyInst, coverage: &'a mut Vec, - timeout: u32, + timeout: Duration, observers: OT, phantom: PhantomData, cur_input: InputFile, - use_stdin: bool, + map: Option<::ShMem>, } -impl<'a, S, OT> std::fmt::Debug for TinyInstExecutor<'a, S, OT> { +impl<'a, S, SP, OT> std::fmt::Debug for TinyInstExecutor<'a, S, SP, OT> +where + SP: ShMemProvider, +{ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("TinyInstExecutor") .field("timeout", &self.timeout) @@ -29,11 +40,12 @@ impl<'a, S, OT> std::fmt::Debug for TinyInstExecutor<'a, S, OT> { } } -impl<'a, EM, S, Z, OT> Executor for TinyInstExecutor<'a, S, OT> +impl<'a, EM, S, SP, OT, Z> Executor for TinyInstExecutor<'a, S, SP, OT> where EM: UsesState, S: UsesInput, S::Input: HasTargetBytes, + SP: ShMemProvider, Z: UsesState, { #[inline] @@ -44,8 +56,22 @@ where _mgr: &mut EM, input: &Self::Input, ) -> Result { - if !self.use_stdin { - self.cur_input.write_buf(input.target_bytes().as_slice())?; + match &self.map { + Some(_) => { + // use shmem to pass testcase + let shmem = unsafe { self.map.as_mut().unwrap_unchecked() }; + let target_bytes = input.target_bytes(); + let size = target_bytes.as_slice().len(); + let size_in_bytes = size.to_ne_bytes(); + // The first four bytes tells the size of the shmem. + shmem.as_mut_slice()[..SHMEM_FUZZ_HDR_SIZE] + .copy_from_slice(&size_in_bytes[..SHMEM_FUZZ_HDR_SIZE]); + shmem.as_mut_slice()[SHMEM_FUZZ_HDR_SIZE..(SHMEM_FUZZ_HDR_SIZE + size)] + .copy_from_slice(target_bytes.as_slice()); + } + None => { + self.cur_input.write_buf(input.target_bytes().as_slice())?; + } } #[allow(unused_assignments)] @@ -66,53 +92,211 @@ where } } -impl<'a, S, OT> TinyInstExecutor<'a, S, OT> -where - OT: ObserversTuple, - S: UsesInput, -{ - /// # Safety - pub unsafe fn new( - coverage: &'a mut Vec, - tinyinst_args: Vec, - program_args: Vec, - timeout: u32, - observers: OT, - ) -> Self { - let mut use_stdin = true; +/// Builder for `TinyInstExecutor` +#[derive(Debug)] +pub struct TinyInstExecutorBuilder<'a, SP> { + tinyinst_args: Vec, + program_args: Vec, + timeout: Duration, + shmem_provider: Option<&'a mut SP>, +} - let program_args = program_args +const MAX_FILE: usize = 1024 * 1024; +const SHMEM_FUZZ_HDR_SIZE: usize = 4; + +impl<'a> Default for TinyInstExecutorBuilder<'a, StdShMemProvider> { + fn default() -> Self { + Self::new() + } +} + +impl<'a> TinyInstExecutorBuilder<'a, StdShMemProvider> { + /// Constructor + #[must_use] + pub fn new() -> TinyInstExecutorBuilder<'a, StdShMemProvider> { + Self { + tinyinst_args: vec![], + program_args: vec![], + timeout: Duration::new(3, 0), + shmem_provider: None, + } + } + + /// Argument for tinyinst instrumentation + #[must_use] + pub fn tinyinst_arg(mut self, arg: String) -> Self { + self.tinyinst_args.push(arg); + self + } + + /// Arguments for tinyinst instrumentation + #[must_use] + pub fn tinyinst_args(mut self, args: Vec) -> Self { + for arg in args { + self.tinyinst_args.push(arg); + } + self + } + + /// The module to instrument. + #[must_use] + pub fn instrument_module(mut self, module: Vec) -> Self { + for modname in module { + self.tinyinst_args.push("-instrument_module".to_string()); + self.tinyinst_args.push(modname); + } + self + } + + /// Use shmem + #[must_use] + pub fn use_shmem(mut self) -> Self { + self.tinyinst_args.push("-delivery".to_string()); + self.tinyinst_args.push("shmem".to_string()); + self + } + + /// Persistent mode + #[must_use] + pub fn persistent( + mut self, + target_module: String, + target_method: String, + nargs: usize, + iterations: usize, + ) -> Self { + self.tinyinst_args.push("-target_module".to_string()); + self.tinyinst_args.push(target_module); + + self.tinyinst_args.push("-target_method".to_string()); + self.tinyinst_args.push(target_method); + + self.tinyinst_args.push("-nargs".to_string()); + self.tinyinst_args.push(nargs.to_string()); + + self.tinyinst_args.push("-iterations".to_string()); + self.tinyinst_args.push(iterations.to_string()); + + self.tinyinst_args.push("-persist".to_string()); + self.tinyinst_args.push("-loop".to_string()); + self + } + + /// Program arg + #[must_use] + pub fn program_arg(mut self, arg: String) -> Self { + self.program_args.push(arg); + self + } + + /// Program args + #[must_use] + pub fn program_args(mut self, args: Vec) -> Self { + for arg in args { + self.program_args.push(arg); + } + self + } + + /// Set timeout + #[must_use] + pub fn timeout(mut self, timeout: Duration) -> Self { + self.timeout = timeout; + self + } + + /// Use this to enable shmem testcase passing. + #[must_use] + pub fn shmem_provider( + self, + shmem_provider: &'a mut SP, + ) -> TinyInstExecutorBuilder<'a, SP> { + TinyInstExecutorBuilder { + tinyinst_args: self.tinyinst_args, + program_args: self.program_args, + timeout: self.timeout, + shmem_provider: Some(shmem_provider), + } + } +} + +impl<'a, SP> TinyInstExecutorBuilder<'a, SP> +where + SP: ShMemProvider, +{ + /// Build tinyinst executor + pub fn build( + &mut self, + coverage: &'a mut Vec, + observers: OT, + ) -> Result, Error> { + let (map, shmem_id) = match &mut self.shmem_provider { + Some(provider) => { + // setup shared memory + let mut shmem = provider.new_shmem(MAX_FILE + SHMEM_FUZZ_HDR_SIZE)?; + let shmem_id = shmem.id(); + // println!("{:#?}", shmem.id()); + // shmem.write_to_env("__TINY_SHM_FUZZ_ID")?; + + let size_in_bytes = (MAX_FILE + SHMEM_FUZZ_HDR_SIZE).to_ne_bytes(); + shmem.as_mut_slice()[..4].clone_from_slice(&size_in_bytes[..4]); + + (Some(shmem), Some(shmem_id)) + } + None => (None, None), + }; + + let mut has_input = false; + let program_args: Vec = self + .program_args + .clone() .into_iter() .map(|arg| { if arg == "@@" { - println!("Not using stdin"); - use_stdin = false; - INPUTFILE_STD.to_string() + has_input = true; + match shmem_id { + Some(shmem_name) => shmem_name.to_string(), + None => INPUTFILE_STD.to_string(), + } } else { arg } }) .collect(); - let cur_input = InputFile::create(INPUTFILE_STD).expect("Unable to create cur_file"); - println!("post init"); - let tinyinst = TinyInst::new(tinyinst_args, program_args, timeout); + if !has_input { + return Err(Error::unknown( + "No input file or shmem provided".to_string(), + )); + } + println!("tinyinst args: {:#?}", &self.tinyinst_args); - Self { + let cur_input = InputFile::create(INPUTFILE_STD).expect("Unable to create cur_file"); + + let tinyinst = unsafe { + TinyInst::new( + &self.tinyinst_args, + &program_args, + self.timeout.as_millis() as u32, + ) + }; + + Ok(TinyInstExecutor { tinyinst, coverage, - timeout, + timeout: self.timeout, observers, phantom: PhantomData, cur_input, - use_stdin, - } + map, + }) } } -impl<'a, S, OT> HasObservers for TinyInstExecutor<'a, S, OT> +impl<'a, S, SP, OT> HasObservers for TinyInstExecutor<'a, S, SP, OT> where S: State, + SP: ShMemProvider, OT: ObserversTuple, { fn observers(&self) -> &OT { @@ -123,16 +307,18 @@ where &mut self.observers } } -impl<'a, S, OT> UsesState for TinyInstExecutor<'a, S, OT> +impl<'a, S, SP, OT> UsesState for TinyInstExecutor<'a, S, SP, OT> where S: UsesInput, + SP: ShMemProvider, { type State = S; } -impl<'a, S, OT> UsesObservers for TinyInstExecutor<'a, S, OT> +impl<'a, S, SP, OT> UsesObservers for TinyInstExecutor<'a, S, SP, OT> where OT: ObserversTuple, S: UsesInput, + SP: ShMemProvider, { type Observers = OT; } diff --git a/libafl_tinyinst/src/lib.rs b/libafl_tinyinst/src/lib.rs index 0c95fdab24..47d70339c1 100644 --- a/libafl_tinyinst/src/lib.rs +++ b/libafl_tinyinst/src/lib.rs @@ -1 +1,69 @@ +/*! +The tinyinst module for `LibAFL`. +*/ + +#![warn(clippy::cargo)] +#![deny(clippy::cargo_common_metadata)] +#![deny(rustdoc::broken_intra_doc_links)] +#![deny(clippy::all)] +#![deny(clippy::pedantic)] +#![allow( + clippy::unreadable_literal, + clippy::type_repetition_in_bounds, + clippy::missing_errors_doc, + clippy::cast_possible_truncation, + clippy::used_underscore_binding, + clippy::ptr_as_ptr, + clippy::missing_panics_doc, + clippy::missing_docs_in_private_items, + clippy::module_name_repetitions, + clippy::unreadable_literal +)] +#![cfg_attr(not(test), warn( + missing_debug_implementations, + missing_docs, + //trivial_casts, + trivial_numeric_casts, + unused_extern_crates, + unused_import_braces, + unused_qualifications, + //unused_results +))] +#![cfg_attr(test, deny( + missing_debug_implementations, + missing_docs, + //trivial_casts, + trivial_numeric_casts, + unused_extern_crates, + unused_import_braces, + unused_qualifications, + unused_must_use, + missing_docs, + //unused_results +))] +#![cfg_attr( + test, + deny( + bad_style, + dead_code, + improper_ctypes, + non_shorthand_field_patterns, + no_mangle_generic_items, + overflowing_literals, + path_statements, + patterns_in_fns_without_body, + private_in_public, + unconditional_recursion, + unused, + unused_allocation, + unused_comparisons, + unused_parens, + while_true + ) +)] +// Till they fix this buggy lint in clippy +#![allow(clippy::borrow_as_ptr)] +#![allow(clippy::borrow_deref_ref)] + +/// Tinyinst executor pub mod executor;