Skip to content

Commit edd4cb1

Browse files
authored
fuzz: Implement IJON for AFL (#132)
1 parent a826d6b commit edd4cb1

5 files changed

Lines changed: 23 additions & 3 deletions

File tree

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ jobs:
3535
- uses: dtolnay/rust-toolchain@master
3636
with:
3737
toolchain: stable
38+
- run: cargo test --no-default-features
3839
- run: cargo test
39-
- run: cargo test --all-features
4040
- run: cargo test --examples
4141
fmt:
4242
name: Rustfmt

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,13 @@ default = ["jetscii"]
3838
# builder with html5gum's tokenizer.
3939
tree-builder = ["html5ever"]
4040

41+
# Features for guided fuzzing using IJON: https://github.com/AFLplusplus/AFLplusplus/blob/stable/docs/IJON.md
42+
afl-ijon = ["afl"]
43+
4144
[dependencies]
4245
html5ever = { version = "0.29.0", optional = true }
4346
jetscii = { version = "0.5.1", optional = true }
47+
afl = { version = "0.17.0", optional = true }
4448

4549
[[bench]]
4650
name = "patterns"

fuzz/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ cargo-fuzz = true
88

99
[dependencies]
1010
libfuzzer-sys = "0.4"
11-
afl = { version = "0.15.15", optional = true }
11+
afl = { version = "0.17.0", optional = true }
1212
html5gum = { path = "../" }
1313
pretty_assertions = "1.0.0"
1414

@@ -24,6 +24,8 @@ lol_html = { version = "2.2", features = ["integration_test"] }
2424
encoding_rs = "0.8"
2525
bytes = "1"
2626

27+
[features]
28+
afl = ["html5gum/afl-ijon", "dep:afl"]
2729

2830
# Prevent this from interfering with workspaces
2931
[workspace]

fuzz/Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ export FUZZ_SWC := 0
88

99
# CLI arguments to pass to AFL. useful for multiprocessing
1010
export _AFL_OPTS := -M fuzzer01
11+
export AFL_LLVM_IJON := 1
12+
export AFL_IJON_HISTORY_LIMIT := 1000
13+
1114
# CLI arguments to cargo fuzz
1215
export _LIBFUZZER_OPTS := -s none
1316

src/machine_helper.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
use crate::utils::trace_log;
22
use crate::{Emitter, Reader, State, Tokenizer};
33

4+
#[cfg(feature = "afl-ijon")]
5+
use afl::{ijon_hashint, ijon_state};
6+
47
#[derive(Debug)]
58
pub(crate) struct MachineState<R: Reader, E: Emitter> {
69
#[allow(clippy::type_complexity)]
@@ -103,8 +106,14 @@ impl<R: Reader, E: Emitter> MachineHelper<R, E> {
103106

104107
pub(crate) fn enter_state(&mut self, state: MachineState<R, E>, is_attribute: bool) {
105108
debug_assert!(self.return_state.is_none());
106-
self.return_state = Some((self.state, is_attribute));
109+
let return_state = (self.state, is_attribute);
110+
self.return_state = Some(return_state);
107111
self.switch_to(state);
112+
#[cfg(feature = "afl-ijon")]
113+
ijon_state!(ijon_hashint(
114+
ijon_hashint(state.function as u32, return_state.0.function as u32),
115+
is_attribute as u32
116+
));
108117
}
109118

110119
pub(crate) fn pop_return_state(&mut self) -> MachineState<R, E> {
@@ -123,6 +132,8 @@ impl<R: Reader, E: Emitter> MachineHelper<R, E> {
123132
state.debug_name
124133
);
125134
self.state = state;
135+
#[cfg(feature = "afl-ijon")]
136+
ijon_state!(state.function as u32);
126137
}
127138
}
128139

0 commit comments

Comments
 (0)