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