Skip to content

Commit 3af042d

Browse files
Merge pull request AFLplusplus#2248 from AFLplusplus/dev
push to stable
2 parents 5777cea + c1e4b8f commit 3af042d

File tree

19 files changed

+225
-31
lines changed

19 files changed

+225
-31
lines changed

GNUmakefile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ VERSION = $(shell grep '^$(HASH)define VERSION ' ../config.h | cut -d '"' -f
3434

3535
PROGS = afl-fuzz afl-showmap afl-tmin afl-gotcpu afl-analyze
3636
SH_PROGS = afl-plot afl-cmin afl-cmin.bash afl-whatsup afl-addseeds afl-system-config afl-persistent-config afl-cc
37-
HEADERS = include/config.h include/types.h
37+
HEADERS = include/afl-as.h include/afl-fuzz.h include/afl-mutations.h include/afl-persistent-replay.h include/afl-prealloc.h include/afl-record-compat.h include/alloc-inl.h include/android-ashmem.h include/cmplog.h include/common.h include/config.h include/coverage-32.h include/coverage-64.h include/debug.h include/envs.h include/forkserver.h include/hash.h include/list.h include/sharedmem.h include/snapshot-inl.h include/t1ha.h include/t1ha0_ia32aes_b.h include/t1ha_bits.h include/t1ha_selfcheck.h include/types.h include/xxhash.h
3838
MANPAGES=$(foreach p, $(PROGS) $(SH_PROGS), $(p).8) afl-as.8
3939
ASAN_OPTIONS=detect_leaks=0
4040

@@ -119,7 +119,7 @@ endif
119119
COMPILER_TYPE=$(shell $(CC) --version|grep "Free Software Foundation")
120120
ifneq "$(COMPILER_TYPE)" ""
121121
#$(info gcc is being used)
122-
override CFLAGS_OPT += -Wno-error=format-truncation -Wno-format-truncation
122+
override CFLAGS_OPT += -Wno-format-truncation
123123
endif
124124

125125
ifeq "$(SYS)" "SunOS"
@@ -578,7 +578,7 @@ code-format:
578578
ifndef AFL_NO_X86
579579
test_build: afl-cc afl-gcc afl-as afl-showmap
580580
@echo "[*] Testing the CC wrapper afl-cc and its instrumentation output..."
581-
@unset AFL_MAP_SIZE AFL_USE_UBSAN AFL_USE_CFISAN AFL_USE_LSAN AFL_USE_ASAN AFL_USE_MSAN; ASAN_OPTIONS=detect_leaks=0 AFL_INST_RATIO=100 AFL_PATH=. ./afl-cc test-instr.c $(LDFLAGS) -o test-instr 2>&1 || (echo "Oops, afl-cc failed"; exit 1 )
581+
@unset AFL_MAP_SIZE AFL_USE_UBSAN AFL_USE_CFISAN AFL_USE_LSAN AFL_USE_ASAN AFL_USE_MSAN AFL_LLVM_ALLOWLIST AFL_LLVM_DENYLIST; ASAN_OPTIONS=detect_leaks=0 AFL_INST_RATIO=100 AFL_PATH=. ./afl-cc test-instr.c $(LDFLAGS) -o test-instr 2>&1 || (echo "Oops, afl-cc failed"; exit 1 )
582582
-ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -q -m none -o .test-instr0 ./test-instr < /dev/null
583583
-echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr
584584
@rm -f test-instr

GNUmakefile.gcc_plugin

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ $(PASSES): instrumentation/afl-gcc-common.h
163163
.PHONY: test_build
164164
test_build: $(PROGS)
165165
@echo "[*] Testing the CC wrapper and instrumentation output..."
166-
unset AFL_USE_ASAN AFL_USE_MSAN; ASAN_OPTIONS=detect_leaks=0 AFL_QUIET=1 AFL_INST_RATIO=100 AFL_PATH=. AFL_CC=$(CC) ./afl-gcc-fast $(CFLAGS) $(CPPFLAGS) ./test-instr.c -o test-instr $(LDFLAGS)
166+
unset AFL_USE_ASAN AFL_USE_MSAN AFL_LLVM_ALLOWLIST AFL_LLVM_DENYLIST; ASAN_OPTIONS=detect_leaks=0 AFL_QUIET=1 AFL_INST_RATIO=100 AFL_PATH=. AFL_CC=$(CC) ./afl-gcc-fast $(CFLAGS) $(CPPFLAGS) ./test-instr.c -o test-instr $(LDFLAGS)
167167
ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr0 ./test-instr </dev/null
168168
echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr
169169
@rm -f test-instr

GNUmakefile.llvm

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ endif
6969

7070
LLVM_STDCXX := gnu++11
7171
LLVM_LTO := 0
72-
LLVM_UNSUPPORTED := $(shell echo "$(LLVMVER)" | grep -E -q '^[0-2]\.|^3\.[0-8]\.' && echo 1 || echo 0)
72+
LLVM_UNSUPPORTED := $(shell echo "$(LLVMVER)" | grep -E -q '^[0-2]\.|^3\.[0-7]\.' && echo 1 || echo 0)
7373
# Uncomment to see the values assigned above
7474
# $(foreach var,LLVM_CONFIG LLVMVER LLVM_MAJOR LLVM_MINOR LLVM_TOO_NEW LLVM_TOO_OLD LLVM_TOO_NEW_DEFAULT LLVM_TOO_OLD_DEFAULT LLVM_NEW_API LLVM_NEWER_API LLVM_13_OK LLVM_HAVE_LTO LLVM_BINDIR LLVM_LIBDIR LLVM_STDCXX LLVM_APPLE_XCODE LLVM_LTO LLVM_UNSUPPORTED,$(warning $(var) = $($(var))))
7575

@@ -508,7 +508,7 @@ document:
508508
.PHONY: test_build
509509
test_build: $(PROGS)
510510
@echo "[*] Testing the CC wrapper and instrumentation output..."
511-
unset AFL_USE_ASAN AFL_USE_MSAN AFL_INST_RATIO; ASAN_OPTIONS=detect_leaks=0 AFL_QUIET=1 AFL_PATH=. AFL_LLVM_LAF_ALL=1 ./afl-cc $(CFLAGS) $(CPPFLAGS) ./test-instr.c -o test-instr $(LDFLAGS)
511+
unset AFL_USE_ASAN AFL_USE_MSAN AFL_INST_RATIO AFL_LLVM_ALLOWLIST AFL_LLVM_DENYLIST; ASAN_OPTIONS=detect_leaks=0 AFL_QUIET=1 AFL_PATH=. AFL_LLVM_LAF_ALL=1 ./afl-cc $(CFLAGS) $(CPPFLAGS) ./test-instr.c -o test-instr $(LDFLAGS)
512512
ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr0 ./test-instr < /dev/null
513513
echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr
514514
@rm -f test-instr

custom_mutators/rust/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ members = [
55
"example",
66
# Lain needs a nightly toolchain
77
# "example_lain",
8-
]
8+
# "example_lain_post_process",
9+
]

custom_mutators/rust/README.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,15 @@ Bindings to create custom mutators in Rust.
55
These bindings are documented with rustdoc. To view the documentation run
66
```cargo doc -p custom_mutator --open```.
77

8-
A minimal example can be found in `example`. Build it using `cargo build --example example_mutator`.
8+
A minimal example can be found in `example`. Build it using `cargo build --example example_mutator`.
99

1010
An example using [lain](https://github.com/microsoft/lain) for structured fuzzing can be found in `example_lain`.
1111
Since lain requires a nightly rust toolchain, you need to set one up before you can play with it.
12+
13+
An example for the use of the post_process function, using [lain](https://github.com/microsoft/lain) with [serde](https://github.com/serde-rs/serde) and [bincode](https://github.com/bincode-org/bincode) can be found in `example_lain_post_process`.
14+
In order for it to work you need to:
15+
16+
- disable input trimming with `AFL_DISABLE_TRIM=1`
17+
- provide an initial instance serialized with `bincode` or use the `AFL_NO_STARTUP_CALIBRATION=1` environment variable.
18+
19+
Note that `bincode` can also be used to serialize/deserialize the lain-generated structure and mutate it rather than generating a new one at each iteration, but it requires some structure serialized with `bincode` as input seed.

custom_mutators/rust/custom_mutator/src/lib.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ pub trait RawCustomMutator {
7373
None
7474
}
7575

76+
fn post_process<'b, 's: 'b>(&'s mut self, buffer: &'b mut [u8]) -> Option<&'b [u8]>;
77+
7678
/*fn post_process(&self, buffer: &[u8], unsigned char **out_buf)-> usize;
7779
int afl_custom_init_trim(&self, buffer: &[u8]);
7880
size_t afl_custom_trim(&self, unsigned char **out_buf);
@@ -353,6 +355,33 @@ pub mod wrappers {
353355
Err(err) => panic_handler("afl_custom_queue_get", &err),
354356
}
355357
}
358+
359+
/// Internal function used in the macro
360+
pub unsafe fn afl_custom_post_process<M: RawCustomMutator>(
361+
data: *mut c_void,
362+
buf: *mut u8,
363+
buf_size: usize,
364+
out_buf: *mut *const u8,
365+
) -> usize {
366+
match catch_unwind(|| {
367+
let mut context = FFIContext::<M>::from(data);
368+
369+
assert!(!buf.is_null(), "null buf passed to afl_custom_post_process");
370+
assert!(
371+
!out_buf.is_null(),
372+
"null out_buf passed to afl_custom_post_process"
373+
);
374+
let buff_slice = slice::from_raw_parts_mut(buf, buf_size);
375+
if let Some(buffer) = context.mutator.post_process(buff_slice) {
376+
*out_buf = buffer.as_ptr();
377+
return buffer.len();
378+
}
379+
0
380+
}) {
381+
Ok(ret) => ret,
382+
Err(err) => panic_handler("afl_custom_post_process", &err),
383+
}
384+
}
356385
}
357386

358387
/// An exported macro to defined afl_custom_init meant for insternal usage
@@ -480,6 +509,16 @@ macro_rules! export_mutator {
480509
pub unsafe extern "C" fn afl_custom_deinit(data: *mut ::std::os::raw::c_void) {
481510
$crate::wrappers::afl_custom_deinit_::<$mutator_type>(data)
482511
}
512+
513+
#[no_mangle]
514+
pub unsafe extern "C" fn afl_custom_post_process(
515+
data: *mut ::std::os::raw::c_void,
516+
buf: *mut u8,
517+
buf_size: usize,
518+
out_buf: *mut *const u8,
519+
) -> usize {
520+
$crate::wrappers::afl_custom_post_process::<$mutator_type>(data, buf, buf_size, out_buf)
521+
}
483522
};
484523
}
485524

@@ -512,6 +551,10 @@ mod sanity_test {
512551
) -> Option<&'b [u8]> {
513552
unimplemented!()
514553
}
554+
555+
fn post_process<'b, 's: 'b>(&'s mut self, buffer: &'b mut [u8]) -> Option<&'b [u8]> {
556+
unimplemented!()
557+
}
515558
}
516559

517560
export_mutator!(ExampleMutator);
@@ -579,6 +622,13 @@ pub trait CustomMutator {
579622
fn introspection(&mut self) -> Result<Option<&str>, Self::Error> {
580623
Ok(None)
581624
}
625+
626+
fn post_process<'b, 's: 'b>(
627+
&'s mut self,
628+
buffer: &'b mut [u8],
629+
) -> Result<Option<&'b [u8]>, Self::Error> {
630+
Ok(Some(buffer))
631+
}
582632
}
583633

584634
impl<M> RawCustomMutator for M
@@ -682,6 +732,16 @@ where
682732
}
683733
}
684734
}
735+
736+
fn post_process<'b, 's: 'b>(&'s mut self, buffer: &'b mut [u8]) -> Option<&'b [u8]> {
737+
match self.post_process(buffer) {
738+
Ok(r) => r,
739+
Err(e) => {
740+
Self::handle_error(e);
741+
None
742+
}
743+
}
744+
}
685745
}
686746

687747
/// the default value to return from [`CustomMutator::describe`].

custom_mutators/rust/example_lain/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ edition = "2021"
88

99
[dependencies]
1010
custom_mutator = { path = "../custom_mutator" }
11-
lain="0.5"
11+
lain = { git = "https://github.com/AFLplusplus/lain.git" }
1212

1313
[[example]]
1414
name = "example_lain"
1515
path = "./src/lain_mutator.rs"
16-
crate-type = ["cdylib"]
16+
crate-type = ["cdylib"]
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
[package]
2+
name = "example_lain_post_process"
3+
version = "0.1.0"
4+
authors = [
5+
"Julius Hohnerlein <julihoh@users.noreply.github.com>",
6+
"jma <94166787+jma-qb@users.noreply.github.com>",
7+
]
8+
edition = "2021"
9+
10+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
11+
12+
[dependencies]
13+
custom_mutator = { path = "../custom_mutator" }
14+
lain = { git = "https://github.com/AFLplusplus/lain.git" }
15+
bincode = "1.3.3"
16+
serde = { version = "1.0.214", features = ["derive"] }
17+
18+
[[example]]
19+
name = "example_lain_post_process"
20+
path = "./src/lain_mutator.rs"
21+
crate-type = ["cdylib"]
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
nightly
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#![cfg(unix)]
2+
3+
use custom_mutator::{export_mutator, CustomMutator};
4+
use lain::{
5+
mutator::Mutator,
6+
prelude::*,
7+
rand::{rngs::StdRng, SeedableRng},
8+
};
9+
use serde::{Deserialize, Serialize};
10+
11+
#[derive(Debug, Deserialize, Serialize, Mutatable, NewFuzzed, BinarySerialize)]
12+
struct MyStruct {
13+
tag: u8,
14+
#[lain(ignore)]
15+
length: u32,
16+
#[lain(min = 0, max = 10)]
17+
data: Vec<u8>,
18+
}
19+
20+
struct LainMutator {
21+
mutator: Mutator<StdRng>,
22+
buffer: Vec<u8>,
23+
post_buffer: Vec<u8>,
24+
}
25+
26+
impl CustomMutator for LainMutator {
27+
type Error = ();
28+
29+
fn init(seed: u32) -> Result<Self, ()> {
30+
Ok(Self {
31+
mutator: Mutator::new(StdRng::seed_from_u64(seed as u64)),
32+
buffer: Vec::new(),
33+
post_buffer: Vec::new(),
34+
})
35+
}
36+
37+
fn fuzz<'b, 's: 'b>(
38+
&'s mut self,
39+
_buffer: &'b mut [u8],
40+
_add_buff: Option<&[u8]>,
41+
max_size: usize,
42+
) -> Result<Option<&'b [u8]>, ()> {
43+
// we just sample an instance of MyStruct, ignoring the current input
44+
let instance = MyStruct::new_fuzzed(&mut self.mutator, None);
45+
let serialized = bincode::serialize(&instance).unwrap();
46+
let size = serialized.len();
47+
if size > max_size {
48+
return Err(());
49+
}
50+
self.buffer.clear();
51+
self.buffer.reserve(size);
52+
self.buffer.extend_from_slice(&serialized);
53+
Ok(Some(self.buffer.as_slice()))
54+
}
55+
56+
fn post_process<'b, 's: 'b>(
57+
&'s mut self,
58+
buffer: &'b mut [u8],
59+
) -> Result<Option<&'b [u8]>, Self::Error> {
60+
let mut instance = bincode::deserialize::<MyStruct>(&buffer).unwrap();
61+
instance.length = instance.data.len() as u32;
62+
let size = instance.serialized_size();
63+
self.post_buffer.clear();
64+
self.post_buffer.reserve(size);
65+
instance.binary_serialize::<_, BigEndian>(&mut self.post_buffer);
66+
Ok(Some(&self.post_buffer))
67+
}
68+
}
69+
70+
export_mutator!(LainMutator);

0 commit comments

Comments
 (0)