From b537539b54045a19f8bfd8b6db479e8584467e4d Mon Sep 17 00:00:00 2001 From: Dongjia Zhang Date: Fri, 31 Dec 2021 00:33:23 +0900 Subject: [PATCH] Use MiMalloc for in-process fuzzers (#439) * MiMalloc * docu * other fuzzers * mention asan --- docs/src/core_concepts/executor.md | 41 +++++++++++++++++ .../forkserver_and_inprocessforkserver.md | 44 ------------------- fuzzers/frida_libpng/Cargo.toml | 1 + fuzzers/frida_libpng/src/fuzzer.rs | 3 ++ fuzzers/fuzzbench/Cargo.toml | 1 + fuzzers/fuzzbench/src/lib.rs | 3 ++ fuzzers/generic_inmemory/Cargo.toml | 1 + fuzzers/generic_inmemory/src/lib.rs | 3 ++ fuzzers/libfuzzer_libmozjpeg/Cargo.toml | 1 + fuzzers/libfuzzer_libmozjpeg/src/lib.rs | 3 ++ fuzzers/libfuzzer_libpng/Cargo.toml | 1 + fuzzers/libfuzzer_libpng/src/lib.rs | 3 ++ fuzzers/libfuzzer_libpng_ctx/Cargo.toml | 1 + fuzzers/libfuzzer_libpng_ctx/src/lib.rs | 3 ++ fuzzers/libfuzzer_libpng_launcher/Cargo.toml | 1 + fuzzers/libfuzzer_libpng_launcher/src/lib.rs | 3 ++ fuzzers/libfuzzer_reachability/Cargo.toml | 1 + fuzzers/libfuzzer_reachability/src/lib.rs | 3 ++ fuzzers/libfuzzer_stb_image/Cargo.toml | 1 + fuzzers/libfuzzer_stb_image/src/main.rs | 3 ++ .../fuzzer/Cargo.toml | 1 + .../fuzzer/src/main.rs | 3 ++ fuzzers/libfuzzer_stb_image_sugar/Cargo.toml | 1 + fuzzers/libfuzzer_stb_image_sugar/src/main.rs | 3 ++ 24 files changed, 85 insertions(+), 44 deletions(-) delete mode 100644 docs/src/core_concepts/forkserver_and_inprocessforkserver.md diff --git a/docs/src/core_concepts/executor.md b/docs/src/core_concepts/executor.md index ae461e43ba..11934f056c 100644 --- a/docs/src/core_concepts/executor.md +++ b/docs/src/core_concepts/executor.md @@ -14,3 +14,44 @@ In Rust, we bind this concept to the [`Executor`](https://docs.rs/libafl/0/libaf By default, we implement some commonly used Executors such as [`InProcessExecutor`](https://docs.rs/libafl/0/libafl/executors/inprocess/struct.InProcessExecutor.html) is which the target is a harness function providing in-process crash detection. Another Executor is the [`ForkserverExecutor`](https://docs.rs/libafl/0/libafl/executors/forkserver/struct.ForkserverExecutor.html) that implements an AFL-like mechanism to spawn child processes to fuzz. A common pattern when creating an Executor is wrapping an existing one, for instance [`TimeoutExecutor`](https://docs.rs/libafl/0.6.1/libafl/executors/timeout/struct.TimeoutExecutor.html) wraps an executor and install a timeout callback before calling the original run function of the wrapped executor. + +## InProcessExecutor +Let's begin with the base case; `InProcessExecutor`. +This executor uses [_SanitizerCoverage_](https://clang.llvm.org/docs/SanitizerCoverage.html) as its backend, as you can find the related code in `libafl_targets/src/sancov_pcguards`. Here we allocate a map called `EDGES_MAP` and then our compiler wrapper compiles the harness to write the coverage into this map. +When you want to execute the harness as fast as possible, you will most probably want to use this `InprocessExecutor`. + One thing to note here is, when your harness is likely to have heap corruption bugs, you want to use another allocator so that corrupted heap does not affect the fuzzer itself. (For example, we adopt MiMalloc in some of our fuzzers.). Alternatively you can compile your harness with address sanitizer to make sure you can catch these heap bugs. + +## ForkserverExecutor +Next, we'll take a look at the `ForkserverExecutor`. In this case, it is `afl-cc` (from AFLplusplus/AFLplusplus) that compiles the harness code, and therefore, we can't use `EDGES_MAP` anymore. Hopefully, we have [_a way_](https://github.com/AFLplusplus/AFLplusplus/blob/2e15661f184c77ac1fbb6f868c894e946cbb7f17/instrumentation/afl-compiler-rt.o.c#L270) to tell the forkserver which map to record the coverage. +As you can see from the forkserver example, +```rust,ignore +//Coverage map shared between observer and executor +let mut shmem = StdShMemProvider::new().unwrap().new_map(MAP_SIZE).unwrap(); +//let the forkserver know the shmid +shmem.write_to_env("__AFL_SHM_ID").unwrap(); +let mut shmem_map = shmem.map_mut(); +``` +Here we make a shared memory region; `shmem`, and write this to environmental variable `__AFL_SHM_ID`. Then the instrumented binary, or the forkserver, finds this shared memory region (from the aforementioned env var) to record its coverage. On your fuzzer side, you can pass this shmem map to your `Observer` to obtain coverage feedbacks combined with any `Feedback`. + +Another feature of the `ForkserverExecutor` to mention is the shared memory testcases. In normal cases, the mutated input is passed between the forkserver and the instrumented binary via `.cur_input` file. You can improve your forkserver fuzzer's performance by passing the input with shared memory. +See AFL++'s [_documentation_](https://github.com/AFLplusplus/AFLplusplus/blob/stable/instrumentation/README.persistent_mode.md#5-shared-memory-fuzzing) or the fuzzer example in `forkserver_simple/src/program.c` for reference. +It is very simple, when you call `ForkserverExecutor::new()` with `use_shmem_testcase` true, the `ForkserverExecutor` sets things up and your harness can just fetch the input from `__AFL_FUZZ_TESTCASE_BUF` + +## InprocessForkExecutor +Finally, we'll talk about the `InProcessForkExecutor`. +`InProcessForkExecutor` has only one difference from `InprocessExecutor`; It forks before running the harness and that's it. +But why do we want to do so? well, under some circumstances, you may find your harness pretty unstable or your harness wreaks havoc on the global states. In this case, you want to fork it before executing the harness runs in the child process so that it doesn't break things. +However, we have to take care of the shared memory, it's the child process that runs the harness code and writes the coverage to the map. +We have to make the map shared between the parent process and the child process, so we'll use shared memory again. You should compile your harness with `pointer_maps` (for `libafl_targes`) features enabled, this way, we can have a pointer; `EDGES_MAP_PTR` that can point to any coverage map. +On your fuzzer side, you can allocate a shared memory region and make the `EDGES_MAP_PTR` point to your shared memory. +```rust,ignore +let mut shmem; +unsafe{ + shmem = StdShMemProvider::new().unwrap().new_map(MAX_EDGES_NUM).unwrap(); +} +let shmem_map = shmem.map_mut(); +unsafe{ + EDGES_PTR = shmem_map.as_ptr(); +} +``` +Again, you can pass this shmem map to your `Observer` and `Feedback` to obtain coverage feedbacks. diff --git a/docs/src/core_concepts/forkserver_and_inprocessforkserver.md b/docs/src/core_concepts/forkserver_and_inprocessforkserver.md deleted file mode 100644 index 8ead0b5c1a..0000000000 --- a/docs/src/core_concepts/forkserver_and_inprocessforkserver.md +++ /dev/null @@ -1,44 +0,0 @@ -# ForkserverExecutor and InprocessForkExecutor - -## Introduction -We have `ForkserverExecutor` and `InprocessForkExecutor` in libafl crate. -On this page, we'll quickly explain how they work and see how they compare to normal `InProcessExecutor` - -## InprocessExecutor -Let's begin with the base case; `InProcessExecutor`. -This executor uses [_SanitizerCoverage_](https://clang.llvm.org/docs/SanitizerCoverage.html) as its backend, as you can find the related code in `libafl_targets/src/sancov_pcguards`. Here we allocate a map called `EDGES_MAP` and then our compiler wrapper compiles the harness to write the coverage into this map. - -## ForkserverExecutor -Next, we'll look at the `ForkserverExecutor`. In this case, it is `afl-cc` (from AFLplusplus/AFLplusplus) that compiles the harness code, and therefore, we can't use `EDGES_MAP` anymore. Hopefully, we have [_a way_](https://github.com/AFLplusplus/AFLplusplus/blob/2e15661f184c77ac1fbb6f868c894e946cbb7f17/instrumentation/afl-compiler-rt.o.c#L270) to tell the forkserver which map to record the coverage. -As you can see from the forkserver example, -```rust,ignore -//Coverage map shared between observer and executor -let mut shmem = StdShMemProvider::new().unwrap().new_map(MAP_SIZE).unwrap(); -//let the forkserver know the shmid -shmem.write_to_env("__AFL_SHM_ID").unwrap(); -let mut shmem_map = shmem.map_mut(); -``` -Here we make a shared memory region; `shmem`, and write this to environmental variable `__AFL_SHM_ID`. Then the instrumented binary, or the forkserver, finds this shared memory region (from the aforementioned env var) to record its coverage. On your fuzzer side, you can pass this shmem map to your `Observer` to obtain coverage feedbacks combined with any `Feedback`. - -Another feature of the `ForkserverExecutor` to mention is the shared memory testcases. In normal cases, the mutated input is passed between the forkserver and the instrumented binary via `.cur_input` file. You can improve your forkserver fuzzer's performance by passing the input with shared memory. -See AFL++'s [_documentation_](https://github.com/AFLplusplus/AFLplusplus/blob/stable/instrumentation/README.persistent_mode.md#5-shared-memory-fuzzing) or the fuzzer example in `forkserver_simple/src/program.c` for reference. -It is very simple, when you call `ForkserverExecutor::new()` with `use_shmem_testcase` true, the `ForkserverExecutor` sets things up and your harness can just fetch the input from `__AFL_FUZZ_TESTCASE_BUF` - -## InprocessForkExecutor -Finally, we'll talk about the `InProcessForkExecutor`. -`InProcessForkExecutor` has only one difference from `InprocessExecutor`; It forks before running the harness and that's it. -But why do we want to do so? well, under some circumstances, you may find your harness pretty unstable or your harness wreaks havoc on the global states. In this case, you want to fork it before executing the harness runs in the child process so that it doesn't break things. -However, we have to take care of the shared memory, it's the child process that runs the harness code and writes the coverage to the map. -We have to make the map shared between the parent process and the child process, so we'll use shared memory again. You should compile your harness with `pointer_maps` (for `libafl_targes`) features enabled, this way, we can have a pointer; `EDGES_MAP_PTR` that can point to any coverage map. -On your fuzzer side, you can allocate a shared memory region and make the `EDGES_MAP_PTR` point to your shared memory. -```rust,ignore -let mut shmem; -unsafe{ - shmem = StdShMemProvider::new().unwrap().new_map(MAX_EDGES_NUM).unwrap(); -} -let shmem_map = shmem.map_mut(); -unsafe{ - EDGES_PTR = shmem_map.as_ptr(); -} -``` -Again, you can pass this shmem map to your `Observer` and `Feedback` to obtain coverage feedbacks. diff --git a/fuzzers/frida_libpng/Cargo.toml b/fuzzers/frida_libpng/Cargo.toml index 80b49f3bca..bbd3ce266e 100644 --- a/fuzzers/frida_libpng/Cargo.toml +++ b/fuzzers/frida_libpng/Cargo.toml @@ -40,6 +40,7 @@ num-traits = "0.2.14" rangemap = "0.1.10" structopt = "0.3.25" serde = "1.0" +mimalloc = { version = "*", default-features = false } backtrace = "0.3" color-backtrace = "0.5" diff --git a/fuzzers/frida_libpng/src/fuzzer.rs b/fuzzers/frida_libpng/src/fuzzer.rs index cbccf1b39c..ccf78c69b1 100644 --- a/fuzzers/frida_libpng/src/fuzzer.rs +++ b/fuzzers/frida_libpng/src/fuzzer.rs @@ -1,5 +1,8 @@ //! A libfuzzer-like fuzzer with llmp-multithreading support and restarts //! The example harness is built for libpng. +use mimalloc::MiMalloc; +#[global_allocator] +static GLOBAL: MiMalloc = MiMalloc; use frida_gum::Gum; use std::{ diff --git a/fuzzers/fuzzbench/Cargo.toml b/fuzzers/fuzzbench/Cargo.toml index e728c5d9c4..e3410e1fcf 100644 --- a/fuzzers/fuzzbench/Cargo.toml +++ b/fuzzers/fuzzbench/Cargo.toml @@ -26,6 +26,7 @@ libafl_targets = { path = "../../libafl_targets/", features = ["sancov_pcguard_h libafl_cc = { path = "../../libafl_cc/" } clap = { version = "3.0.0-rc.4", features = ["default"] } nix = "0.23.0" +mimalloc = { version = "*", default-features = false } [lib] name = "fuzzbench" diff --git a/fuzzers/fuzzbench/src/lib.rs b/fuzzers/fuzzbench/src/lib.rs index f010df48d7..ec71be1b1e 100644 --- a/fuzzers/fuzzbench/src/lib.rs +++ b/fuzzers/fuzzbench/src/lib.rs @@ -1,4 +1,7 @@ //! A singlethreaded libfuzzer-like fuzzer that can auto-restart. +use mimalloc::MiMalloc; +#[global_allocator] +static GLOBAL: MiMalloc = MiMalloc; use clap::{App, Arg}; use core::{cell::RefCell, time::Duration}; diff --git a/fuzzers/generic_inmemory/Cargo.toml b/fuzzers/generic_inmemory/Cargo.toml index c080a13135..e842a56836 100644 --- a/fuzzers/generic_inmemory/Cargo.toml +++ b/fuzzers/generic_inmemory/Cargo.toml @@ -25,6 +25,7 @@ libafl_targets = { path = "../../libafl_targets/", features = ["sancov_pcguard_h # TODO Include it only when building cc libafl_cc = { path = "../../libafl_cc/" } structopt = "0.3.25" +mimalloc = { version = "*", default-features = false } [lib] name = "generic_inmemory" diff --git a/fuzzers/generic_inmemory/src/lib.rs b/fuzzers/generic_inmemory/src/lib.rs index cbc8d7c4f2..60d62ab56a 100644 --- a/fuzzers/generic_inmemory/src/lib.rs +++ b/fuzzers/generic_inmemory/src/lib.rs @@ -1,5 +1,8 @@ //! A libfuzzer-like fuzzer with llmp-multithreading support and restarts //! The `launcher` will spawn new processes for each cpu core. +use mimalloc::MiMalloc; +#[global_allocator] +static GLOBAL: MiMalloc = MiMalloc; use core::time::Duration; use std::{env, net::SocketAddr, path::PathBuf}; diff --git a/fuzzers/libfuzzer_libmozjpeg/Cargo.toml b/fuzzers/libfuzzer_libmozjpeg/Cargo.toml index 544fa8f7b8..94d8f48eba 100644 --- a/fuzzers/libfuzzer_libmozjpeg/Cargo.toml +++ b/fuzzers/libfuzzer_libmozjpeg/Cargo.toml @@ -19,6 +19,7 @@ libafl = { path = "../../libafl/" } libafl_targets = { path = "../../libafl_targets/", features = ["sancov_pcguard_edges", "sancov_value_profile", "libfuzzer"] } # TODO Include it only when building cc libafl_cc = { path = "../../libafl_cc/" } +mimalloc = { version = "*", default-features = false } [build-dependencies] cc = { version = "1.0", features = ["parallel"] } diff --git a/fuzzers/libfuzzer_libmozjpeg/src/lib.rs b/fuzzers/libfuzzer_libmozjpeg/src/lib.rs index 9c7e0dfe96..ddcbc5907a 100644 --- a/fuzzers/libfuzzer_libmozjpeg/src/lib.rs +++ b/fuzzers/libfuzzer_libmozjpeg/src/lib.rs @@ -1,5 +1,8 @@ //! A libfuzzer-like fuzzer with llmp-multithreading support and restarts //! The example harness is built for libmozjpeg. +use mimalloc::MiMalloc; +#[global_allocator] +static GLOBAL: MiMalloc = MiMalloc; use std::{env, path::PathBuf}; diff --git a/fuzzers/libfuzzer_libpng/Cargo.toml b/fuzzers/libfuzzer_libpng/Cargo.toml index dd2867b7c7..7246771b71 100644 --- a/fuzzers/libfuzzer_libpng/Cargo.toml +++ b/fuzzers/libfuzzer_libpng/Cargo.toml @@ -25,6 +25,7 @@ libafl = { path = "../../libafl/", features = ["default"] } libafl_targets = { path = "../../libafl_targets/", features = ["sancov_pcguard_hitcounts", "libfuzzer", "sancov_cmplog"] } # TODO Include it only when building cc libafl_cc = { path = "../../libafl_cc/" } +mimalloc = { version = "*", default-features = false } [lib] name = "libfuzzer_libpng" diff --git a/fuzzers/libfuzzer_libpng/src/lib.rs b/fuzzers/libfuzzer_libpng/src/lib.rs index b1367d442f..dc3810f15f 100644 --- a/fuzzers/libfuzzer_libpng/src/lib.rs +++ b/fuzzers/libfuzzer_libpng/src/lib.rs @@ -1,5 +1,8 @@ //! A libfuzzer-like fuzzer with llmp-multithreading support and restarts //! The example harness is built for libpng. +use mimalloc::MiMalloc; +#[global_allocator] +static GLOBAL: MiMalloc = MiMalloc; use core::time::Duration; use std::{env, path::PathBuf}; diff --git a/fuzzers/libfuzzer_libpng_ctx/Cargo.toml b/fuzzers/libfuzzer_libpng_ctx/Cargo.toml index b589d6762b..452edd9560 100644 --- a/fuzzers/libfuzzer_libpng_ctx/Cargo.toml +++ b/fuzzers/libfuzzer_libpng_ctx/Cargo.toml @@ -25,6 +25,7 @@ libafl_targets = { path = "../../libafl_targets/", features = ["libfuzzer"] } # TODO Include it only when building cc libafl_cc = { path = "../../libafl_cc/" } structopt = "0.3.25" +mimalloc = { version = "*", default-features = false } [lib] name = "libfuzzer_libpng" diff --git a/fuzzers/libfuzzer_libpng_ctx/src/lib.rs b/fuzzers/libfuzzer_libpng_ctx/src/lib.rs index f87417466c..414b89dcc8 100644 --- a/fuzzers/libfuzzer_libpng_ctx/src/lib.rs +++ b/fuzzers/libfuzzer_libpng_ctx/src/lib.rs @@ -2,6 +2,9 @@ //! The example harness is built for libpng. //! In this example, you will see the use of the `launcher` feature. //! The `launcher` will spawn new processes for each cpu core. +use mimalloc::MiMalloc; +#[global_allocator] +static GLOBAL: MiMalloc = MiMalloc; use core::time::Duration; use std::{env, net::SocketAddr, path::PathBuf}; diff --git a/fuzzers/libfuzzer_libpng_launcher/Cargo.toml b/fuzzers/libfuzzer_libpng_launcher/Cargo.toml index b225e962c5..7c70283460 100644 --- a/fuzzers/libfuzzer_libpng_launcher/Cargo.toml +++ b/fuzzers/libfuzzer_libpng_launcher/Cargo.toml @@ -25,6 +25,7 @@ libafl_targets = { path = "../../libafl_targets/", features = ["sancov_pcguard_h # TODO Include it only when building cc libafl_cc = { path = "../../libafl_cc/" } structopt = "0.3.25" +mimalloc = { version = "*", default-features = false } [lib] name = "libfuzzer_libpng" diff --git a/fuzzers/libfuzzer_libpng_launcher/src/lib.rs b/fuzzers/libfuzzer_libpng_launcher/src/lib.rs index 5d63d2c4e4..77daf9c526 100644 --- a/fuzzers/libfuzzer_libpng_launcher/src/lib.rs +++ b/fuzzers/libfuzzer_libpng_launcher/src/lib.rs @@ -2,6 +2,9 @@ //! The example harness is built for libpng. //! In this example, you will see the use of the `launcher` feature. //! The `launcher` will spawn new processes for each cpu core. +use mimalloc::MiMalloc; +#[global_allocator] +static GLOBAL: MiMalloc = MiMalloc; use core::time::Duration; use std::{env, net::SocketAddr, path::PathBuf}; diff --git a/fuzzers/libfuzzer_reachability/Cargo.toml b/fuzzers/libfuzzer_reachability/Cargo.toml index 9a36f60c8f..129c503011 100644 --- a/fuzzers/libfuzzer_reachability/Cargo.toml +++ b/fuzzers/libfuzzer_reachability/Cargo.toml @@ -24,6 +24,7 @@ libafl = { path = "../../libafl/" } libafl_targets = { path = "../../libafl_targets/", features = ["sancov_pcguard_hitcounts", "libfuzzer"] } # TODO Include it only when building cc libafl_cc = { path = "../../libafl_cc/" } +mimalloc = { version = "*", default-features = false } [lib] name = "libfuzzer_libpng" diff --git a/fuzzers/libfuzzer_reachability/src/lib.rs b/fuzzers/libfuzzer_reachability/src/lib.rs index eed219ebd9..4d27fa8e92 100644 --- a/fuzzers/libfuzzer_reachability/src/lib.rs +++ b/fuzzers/libfuzzer_reachability/src/lib.rs @@ -1,5 +1,8 @@ //! A libfuzzer-like fuzzer with llmp-multithreading support and restarts //! The example harness is built for libpng. +use mimalloc::MiMalloc; +#[global_allocator] +static GLOBAL: MiMalloc = MiMalloc; use std::{env, path::PathBuf}; diff --git a/fuzzers/libfuzzer_stb_image/Cargo.toml b/fuzzers/libfuzzer_stb_image/Cargo.toml index ff8639623c..980ab304ba 100644 --- a/fuzzers/libfuzzer_stb_image/Cargo.toml +++ b/fuzzers/libfuzzer_stb_image/Cargo.toml @@ -18,6 +18,7 @@ debug = true [dependencies] libafl = { path = "../../libafl/" } libafl_targets = { path = "../../libafl_targets/", features = ["sancov_pcguard_edges", "sancov_cmplog", "libfuzzer"] } +mimalloc = { version = "*", default-features = false } [build-dependencies] cc = { version = "1.0", features = ["parallel"] } diff --git a/fuzzers/libfuzzer_stb_image/src/main.rs b/fuzzers/libfuzzer_stb_image/src/main.rs index c89e26f21e..810251735e 100644 --- a/fuzzers/libfuzzer_stb_image/src/main.rs +++ b/fuzzers/libfuzzer_stb_image/src/main.rs @@ -1,5 +1,8 @@ //! A libfuzzer-like fuzzer with llmp-multithreading support and restarts //! The example harness is built for `stb_image`. +use mimalloc::MiMalloc; +#[global_allocator] +static GLOBAL: MiMalloc = MiMalloc; use std::{env, path::PathBuf}; diff --git a/fuzzers/libfuzzer_stb_image_concolic/fuzzer/Cargo.toml b/fuzzers/libfuzzer_stb_image_concolic/fuzzer/Cargo.toml index 5c47a68919..95adad50f2 100644 --- a/fuzzers/libfuzzer_stb_image_concolic/fuzzer/Cargo.toml +++ b/fuzzers/libfuzzer_stb_image_concolic/fuzzer/Cargo.toml @@ -19,6 +19,7 @@ debug = true libafl = { path = "../../../libafl/", features = ["concolic_mutation"] } libafl_targets = { path = "../../../libafl_targets/", features = ["sancov_pcguard_edges", "sancov_cmplog", "libfuzzer"] } structopt = "0.3.21" +mimalloc = { version = "*", default-features = false } [build-dependencies] cc = { version = "1.0", features = ["parallel"] } diff --git a/fuzzers/libfuzzer_stb_image_concolic/fuzzer/src/main.rs b/fuzzers/libfuzzer_stb_image_concolic/fuzzer/src/main.rs index 2cb9cdb8c5..dc1d642e66 100644 --- a/fuzzers/libfuzzer_stb_image_concolic/fuzzer/src/main.rs +++ b/fuzzers/libfuzzer_stb_image_concolic/fuzzer/src/main.rs @@ -1,5 +1,8 @@ //! A libfuzzer-like fuzzer with llmp-multithreading support and restarts //! The example harness is built for `stb_image`. +use mimalloc::MiMalloc; +#[global_allocator] +static GLOBAL: MiMalloc = MiMalloc; use std::{env, path::PathBuf}; diff --git a/fuzzers/libfuzzer_stb_image_sugar/Cargo.toml b/fuzzers/libfuzzer_stb_image_sugar/Cargo.toml index 2aaf2052a5..6ac790e013 100644 --- a/fuzzers/libfuzzer_stb_image_sugar/Cargo.toml +++ b/fuzzers/libfuzzer_stb_image_sugar/Cargo.toml @@ -19,6 +19,7 @@ debug = true libafl = { path = "../../libafl/" } libafl_targets = { path = "../../libafl_targets/", features = ["sancov_pcguard_edges", "sancov_cmplog", "libfuzzer"] } libafl_sugar = { path = "../../libafl_sugar/" } +mimalloc = { version = "*", default-features = false } [build-dependencies] cc = { version = "1.0", features = ["parallel"] } diff --git a/fuzzers/libfuzzer_stb_image_sugar/src/main.rs b/fuzzers/libfuzzer_stb_image_sugar/src/main.rs index 2b377bf680..37d2c1e2b7 100644 --- a/fuzzers/libfuzzer_stb_image_sugar/src/main.rs +++ b/fuzzers/libfuzzer_stb_image_sugar/src/main.rs @@ -1,5 +1,8 @@ //! A libfuzzer-like fuzzer with llmp-multithreading support and restarts //! The example harness is built for `stb_image`. +use mimalloc::MiMalloc; +#[global_allocator] +static GLOBAL: MiMalloc = MiMalloc; use std::{env, path::PathBuf};