libafl/
lib.rs

1/*!
2Welcome to `LibAFL`
3*/
4#![doc = include_str!("../README.md")]
5/*! */
6#![cfg_attr(feature = "document-features", doc = document_features::document_features!())]
7#![no_std]
8// For `type_eq`
9#![cfg_attr(nightly, feature(specialization))]
10// For `std::simd`
11#![cfg_attr(nightly, feature(portable_simd))]
12#![cfg_attr(
13    not(test),
14    warn(
15        missing_debug_implementations,
16        missing_docs,
17        trivial_numeric_casts,
18        unused_extern_crates,
19        unused_import_braces,
20        unused_qualifications,
21    )
22)]
23#![cfg_attr(
24    test,
25    deny(
26        bad_style,
27        dead_code,
28        improper_ctypes,
29        missing_debug_implementations,
30        missing_docs,
31        no_mangle_generic_items,
32        non_shorthand_field_patterns,
33        overflowing_literals,
34        path_statements,
35        patterns_in_fns_without_body,
36        trivial_numeric_casts,
37        unconditional_recursion,
38        unfulfilled_lint_expectations,
39        unused_allocation,
40        unused_comparisons,
41        unused_extern_crates,
42        unused_import_braces,
43        unused_must_use,
44        unused_parens,
45        unused_qualifications,
46        unused,
47        while_true
48    )
49)]
50
51#[cfg(feature = "std")]
52#[macro_use]
53extern crate std;
54#[macro_use]
55#[doc(hidden)]
56pub extern crate alloc;
57
58// Re-export derive(SerdeAny)
59#[cfg(feature = "derive")]
60#[expect(unused_imports)]
61#[macro_use]
62extern crate libafl_derive;
63#[cfg(feature = "derive")]
64#[doc(hidden)]
65pub use libafl_derive::*;
66
67pub mod common;
68pub use common::*;
69pub mod corpus;
70pub mod events;
71pub mod executors;
72pub mod feedbacks;
73pub mod fuzzer;
74pub mod generators;
75pub mod inputs;
76pub mod monitors;
77pub mod mutators;
78pub mod observers;
79pub mod schedulers;
80pub mod stages;
81pub mod state;
82
83pub use fuzzer::*;
84pub use libafl_bolts::{Error, nonzero};
85
86/// The purpose of this module is to alleviate imports of many components by adding a glob import.
87#[cfg(feature = "prelude")]
88pub mod prelude {
89    #![expect(ambiguous_glob_reexports)]
90
91    pub use super::{
92        corpus::*, events::*, executors::*, feedbacks::*, fuzzer::*, generators::*, inputs::*,
93        monitors::*, mutators::*, observers::*, schedulers::*, stages::*, state::*, *,
94    };
95}
96
97#[cfg(all(any(doctest, test), not(feature = "std")))]
98/// Provide custom time in `no_std` tests.
99#[unsafe(no_mangle)]
100pub unsafe extern "C" fn external_current_millis() -> u64 {
101    // TODO: use "real" time here
102    1000
103}
104
105#[cfg(feature = "std")]
106#[cfg(test)]
107mod tests {
108
109    #[cfg(miri)]
110    use libafl_bolts::serdeany::RegistryBuilder;
111    use libafl_bolts::{
112        rands::{RomuDuoJrRand, StdRand},
113        tuples::tuple_list,
114    };
115
116    #[cfg(miri)]
117    use crate::stages::ExecutionCountRestartHelperMetadata;
118    use crate::{
119        StdFuzzer,
120        corpus::{Corpus, InMemoryCorpus, Testcase},
121        events::NopEventManager,
122        executors::{ExitKind, InProcessExecutor},
123        feedbacks::ConstFeedback,
124        fuzzer::Fuzzer,
125        inputs::BytesInput,
126        monitors::SimpleMonitor,
127        mutators::{StdScheduledMutator, mutations::BitFlipMutator},
128        schedulers::RandScheduler,
129        stages::StdMutationalStage,
130        state::{HasCorpus, StdState},
131    };
132
133    #[test]
134    fn test_fuzzer() {
135        // # Safety
136        // No concurrency per testcase
137        #[cfg(miri)]
138        unsafe {
139            RegistryBuilder::register::<ExecutionCountRestartHelperMetadata>();
140        }
141
142        let rand = StdRand::with_seed(0);
143
144        let mut corpus = InMemoryCorpus::<BytesInput>::new();
145        let testcase = Testcase::new(vec![0; 4].into());
146        corpus.add(testcase).unwrap();
147
148        let mut feedback = ConstFeedback::new(false);
149        let mut objective = ConstFeedback::new(false);
150
151        let mut state = StdState::new(
152            rand,
153            corpus,
154            InMemoryCorpus::<BytesInput>::new(),
155            &mut feedback,
156            &mut objective,
157        )
158        .unwrap();
159
160        let _monitor = SimpleMonitor::new(|s| {
161            println!("{s}");
162        });
163        let mut event_manager = NopEventManager::new();
164
165        let feedback = ConstFeedback::new(false);
166        let objective = ConstFeedback::new(false);
167
168        let scheduler = RandScheduler::new();
169        let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective);
170
171        let mut harness = |_buf: &BytesInput| ExitKind::Ok;
172        let mut executor = InProcessExecutor::new(
173            &mut harness,
174            tuple_list!(),
175            &mut fuzzer,
176            &mut state,
177            &mut event_manager,
178        )
179        .unwrap();
180
181        let mutator = StdScheduledMutator::new(tuple_list!(BitFlipMutator::new()));
182        let mut stages = tuple_list!(StdMutationalStage::new(mutator));
183
184        for i in 0..1000 {
185            fuzzer
186                .fuzz_one(&mut stages, &mut executor, &mut state, &mut event_manager)
187                .unwrap_or_else(|_| panic!("Error in iter {i}"));
188            if cfg!(miri) {
189                break;
190            }
191        }
192
193        let state_serialized = postcard::to_allocvec(&state).unwrap();
194        let state_deserialized: StdState<
195            InMemoryCorpus<BytesInput>,
196            _,
197            StdRand,
198            InMemoryCorpus<BytesInput>,
199        > = postcard::from_bytes::<
200            StdState<
201                InMemoryCorpus<BytesInput>,
202                BytesInput,
203                RomuDuoJrRand,
204                InMemoryCorpus<BytesInput>,
205            >,
206        >(state_serialized.as_slice())
207        .unwrap();
208        assert_eq!(state.corpus().count(), state_deserialized.corpus().count());
209
210        let corpus_serialized = postcard::to_allocvec(state.corpus()).unwrap();
211        let corpus_deserialized: InMemoryCorpus<BytesInput> =
212            postcard::from_bytes(corpus_serialized.as_slice()).unwrap();
213        assert_eq!(state.corpus().count(), corpus_deserialized.count());
214    }
215}