Introduce TuiMonitor builder, clean up monitor docs and names (#2385)

* Introduce TuiMonitor builder

* Some random docs

* More documentation for monitors

* fixed critical whitespace

* Rename all-caps TOML and JSON to Toml and Json in monitors

* actually rename

* more
This commit is contained in:
Dominik Maier 2024-07-12 15:27:45 +02:00 committed by GitHub
parent 24aa640df7
commit 3c93b96b70
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 191 additions and 102 deletions

View File

@ -6,6 +6,6 @@ Mutators can be composed, and they are generally linked to a specific Input type
There can be, for instance, a Mutator that applies more than a single type of mutation to the input. Consider a generic Mutator for a byte stream, bit flip is just one of the possible mutations but not the only one, there is also, for instance, the random replacement of a byte of the copy of a chunk.
There are also mutators that always produce valid inputs, say a mutator that generates valid JSON or code, but these grammar based mutators need a grammar to work.
There are also mutators that always produce valid inputs, say a mutator that generates valid Json or code, but these grammar based mutators need a grammar to work.
In LibAFL, [`Mutator`](https://docs.rs/libafl/latest/libafl/mutators/trait.Mutator.html) is a trait.

View File

@ -3,7 +3,7 @@ use std::ptr::write_volatile;
use std::{path::PathBuf, ptr::write};
#[cfg(feature = "tui")]
use libafl::monitors::tui::{ui::TuiUI, TuiMonitor};
use libafl::monitors::tui::TuiMonitor;
#[cfg(not(feature = "tui"))]
use libafl::monitors::SimpleMonitor;
use libafl::{
@ -118,9 +118,10 @@ pub fn main() {
#[cfg(not(feature = "tui"))]
let mon = SimpleMonitor::new(|s| println!("{s}"));
#[cfg(feature = "tui")]
let ui = TuiUI::with_version(String::from("Baby Fuzzer"), String::from("0.0.1"), false);
#[cfg(feature = "tui")]
let mon = TuiMonitor::new(ui);
let mon = TuiMonitor::builder()
.title("Baby Fuzzer")
.enhanced_graphics(false)
.build();
// The event manager handle the various events generated during the fuzzing loop
// such as the notification of the addition of a new item to the corpus

View File

@ -6,7 +6,7 @@ use std::{
};
#[cfg(feature = "tui")]
use libafl::monitors::tui::{ui::TuiUI, TuiMonitor};
use libafl::monitors::tui::TuiMonitor;
#[cfg(not(feature = "tui"))]
use libafl::monitors::SimpleMonitor;
use libafl::{
@ -204,9 +204,10 @@ pub fn main() {
#[cfg(not(feature = "tui"))]
let mon = SimpleMonitor::with_user_monitor(|s| println!("{s}"));
#[cfg(feature = "tui")]
let ui = TuiUI::new(String::from("Baby Fuzzer"), false);
#[cfg(feature = "tui")]
let mon = TuiMonitor::new(ui);
let mon = TuiMonitor::builder()
.title("Baby Fuzzer")
.enhanced_graphics(false)
.build();
// The event manager handle the various events generated during the fuzzing loop
// such as the notification of the addition of a new item to the corpus

View File

@ -3,7 +3,7 @@ use std::ptr::write_volatile;
use std::{path::PathBuf, ptr::write};
#[cfg(feature = "tui")]
use libafl::monitors::tui::{ui::TuiUI, TuiMonitor};
use libafl::monitors::tui::TuiMonitor;
#[cfg(not(feature = "tui"))]
use libafl::monitors::SimpleMonitor;
use libafl::{
@ -85,9 +85,11 @@ pub fn main() {
#[cfg(not(feature = "tui"))]
let mon = SimpleMonitor::new(|s| println!("{s}"));
#[cfg(feature = "tui")]
let ui = TuiUI::with_version(String::from("Baby Fuzzer"), String::from("0.0.1"), false);
#[cfg(feature = "tui")]
let mon = TuiMonitor::new(ui);
let mon = TuiMonitor::builder()
.title("Baby Fuzzer")
.version("0.0.1")
.enhanced_graphics(false)
.build();
// The event manager handle the various events generated during the fuzzing loop
// such as the notification of the addition of a new item to the corpus

View File

@ -25,7 +25,7 @@ def concatenate_json_files(input_dir):
with open(output_file, 'w') as file:
json.dump([data], file)
print(f"JSON files concatenated successfully! Output file: {output_file}")
print(f"Json files concatenated successfully! Output file: {output_file}")
if __name__ == '__main__':
if len(sys.argv) != 2:

View File

@ -4,7 +4,7 @@
#include <string.h>
extern "C" __declspec(dllexport) size_t
LLVMFuzzerTestOneInput(const char *data, unsigned int len) {
LLVMFuzzerTestOneInput(const char *data, unsigned int len) {
if (data[0] == 'b') {
if (data[1] == 'a') {
if (data[2] == 'd') {

View File

@ -13,7 +13,7 @@ use libafl::{
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
fuzzer::{Fuzzer, StdFuzzer},
inputs::{BytesInput, HasTargetBytes},
monitors::tui::{ui::TuiUI, TuiMonitor},
monitors::tui::TuiMonitor,
mutators::{
scheduled::{havoc_mutations, tokens_mutations, StdScheduledMutator},
token_mutations::Tokens,
@ -70,12 +70,12 @@ fn fuzz(
// let monitor = MultiMonitor::new(|s| println!("{s}"));
//Setup an Monitor with AFL-Style UI to display the stats
let ui = TuiUI::with_version(
String::from("Libfuzzer For Libpng"),
String::from("0.0.1"),
false,
);
let monitor = TuiMonitor::new(ui);
#[cfg(feature = "tui")]
let monitor = TuiMonitor::builder()
.title("Libfuzzer in LibAFL")
.version("0.0.1")
.enhanced_graphics(true)
.build();
// The restarting state will spawn the same process again as child, then restarted it each time it crashes.
let (state, mut restarting_mgr) =

View File

@ -14,7 +14,7 @@ use libafl::{
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
fuzzer::{Fuzzer, StdFuzzer},
inputs::{BytesInput, HasTargetBytes},
monitors::{MultiMonitor, OnDiskTOMLMonitor},
monitors::{MultiMonitor, OnDiskTomlMonitor},
mutators::{
scheduled::{havoc_mutations, tokens_mutations, StdScheduledMutator},
token_mutations::Tokens,
@ -131,7 +131,7 @@ pub extern "C" fn libafl_main() {
let shmem_provider = StdShMemProvider::new().expect("Failed to init shared memory");
let monitor = OnDiskTOMLMonitor::new(
let monitor = OnDiskTomlMonitor::new(
"./fuzzer_stats.toml",
MultiMonitor::new(|s| println!("{s}")),
);

View File

@ -18,7 +18,7 @@ use libafl::{
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
fuzzer::{Fuzzer, StdFuzzer},
inputs::{BytesInput, HasTargetBytes},
monitors::{MultiMonitor, OnDiskTOMLMonitor},
monitors::{MultiMonitor, OnDiskTomlMonitor},
mutators::{
scheduled::{havoc_mutations, tokens_mutations, StdScheduledMutator},
token_mutations::Tokens,
@ -154,7 +154,7 @@ pub extern "C" fn libafl_main() {
let shmem_provider = MmapShMemProvider::new().expect("Failed to init shared memory");
let monitor = OnDiskTOMLMonitor::new(
let monitor = OnDiskTomlMonitor::new(
"./fuzzer_stats.toml",
MultiMonitor::new(|s| println!("{s}")),
);

View File

@ -5,7 +5,7 @@ use libafl::{
events::SimpleEventManager,
feedbacks::{CrashFeedback, MaxMapFeedback},
inputs::BytesInput,
monitors::tui::{ui::TuiUI, TuiMonitor},
monitors::tui::TuiMonitor,
mutators::{havoc_mutations, StdScheduledMutator},
observers::StdMapObserver,
schedulers::RandScheduler,
@ -40,8 +40,7 @@ fn main() {
// switch monitor if you want
// let monitor = SimpleMonitor::new(|x|-> () {println!("{}",x)});
let ui = TuiUI::new(String::from("test_fuzz"), true);
let monitor = TuiMonitor::new(ui);
let monitor = TuiMonitor::builder().title("test_fuzz").build();
let mut mgr = SimpleEventManager::new(monitor);
let mut executor = NyxExecutor::builder().build(helper, tuple_list!(observer));

View File

@ -10,10 +10,7 @@ use libafl::events::SimpleEventManager;
#[cfg(not(feature = "simplemgr"))]
use libafl::events::{EventConfig, Launcher, MonitorTypedEventManager};
use libafl::{
monitors::{
tui::{ui::TuiUI, TuiMonitor},
Monitor, MultiMonitor,
},
monitors::{tui::TuiMonitor, Monitor, MultiMonitor},
Error,
};
#[cfg(feature = "simplemgr")]
@ -42,9 +39,11 @@ impl Fuzzer {
pub fn fuzz(&self) -> Result<(), Error> {
if self.options.tui {
let ui =
TuiUI::with_version(String::from("QEMU Launcher"), String::from("0.10.1"), true);
let monitor = TuiMonitor::new(ui);
let monitor = TuiMonitor::builder()
.title("QEMU Launcher")
.version("0.13.1")
.enhanced_graphics(true)
.build();
self.launch(monitor)
} else {
let log = self.options.log.as_ref().and_then(|l| {

View File

@ -24,9 +24,9 @@ use crate::{
pub enum OnDiskMetadataFormat {
/// A binary-encoded postcard
Postcard,
/// JSON
/// Json
Json,
/// JSON formatted for readability
/// Json formatted for readability
#[default]
JsonPretty,
/// The same as [`OnDiskMetadataFormat::JsonPretty`], but compressed

View File

@ -1,4 +1,4 @@
//! Monitors that wrap a base one and log on disk
//! Monitors that wrap a base monitor and also log to disk using different formats.
use alloc::{string::String, vec::Vec};
use core::time::Duration;
@ -13,9 +13,9 @@ use serde_json::json;
use crate::monitors::{ClientStats, Monitor, NopMonitor};
/// Wrap a monitor and log the current state of the monitor into a TOML file.
/// Wrap a monitor and log the current state of the monitor into a Toml file.
#[derive(Debug, Clone)]
pub struct OnDiskTOMLMonitor<M>
pub struct OnDiskTomlMonitor<M>
where
M: Monitor,
{
@ -25,7 +25,7 @@ where
update_interval: Duration,
}
impl<M> Monitor for OnDiskTOMLMonitor<M>
impl<M> Monitor for OnDiskTomlMonitor<M>
where
M: Monitor,
{
@ -59,10 +59,10 @@ where
if cur_time - self.last_update >= self.update_interval {
self.last_update = cur_time;
let mut file = File::create(&self.filename).expect("Failed to open the TOML file");
let mut file = File::create(&self.filename).expect("Failed to open the Toml file");
write!(
&mut file,
"# This TOML is generated using the OnDiskMonitor component of LibAFL
"# This Toml is generated using the OnDiskMonitor component of LibAFL
[global]
run_time = \"{}\"
@ -79,7 +79,7 @@ exec_sec = {}
self.total_execs(),
self.execs_per_sec()
)
.expect("Failed to write to the TOML file");
.expect("Failed to write to the Toml file");
for (i, client) in self.client_stats_mut().iter_mut().enumerate() {
let exec_sec = client.execs_per_sec(cur_time);
@ -95,7 +95,7 @@ exec_sec = {}
",
i, client.corpus_size, client.objective_size, client.executions, exec_sec
)
.expect("Failed to write to the TOML file");
.expect("Failed to write to the Toml file");
for (key, val) in &client.user_monitor {
let k: String = key
@ -104,7 +104,7 @@ exec_sec = {}
.filter(|c| c.is_alphanumeric() || *c == '_')
.collect();
writeln!(&mut file, "{k} = \"{val}\"")
.expect("Failed to write to the TOML file");
.expect("Failed to write to the Toml file");
}
}
@ -115,11 +115,11 @@ exec_sec = {}
}
}
impl<M> OnDiskTOMLMonitor<M>
impl<M> OnDiskTomlMonitor<M>
where
M: Monitor,
{
/// Create new [`OnDiskTOMLMonitor`]
/// Create new [`OnDiskTomlMonitor`]
#[must_use]
pub fn new<P>(filename: P, base: M) -> Self
where
@ -128,7 +128,7 @@ where
Self::with_update_interval(filename, base, Duration::from_secs(60))
}
/// Create new [`OnDiskTOMLMonitor`] with custom update interval
/// Create new [`OnDiskTomlMonitor`] with custom update interval
#[must_use]
pub fn with_update_interval<P>(filename: P, base: M, update_interval: Duration) -> Self
where
@ -143,8 +143,8 @@ where
}
}
impl OnDiskTOMLMonitor<NopMonitor> {
/// Create new [`OnDiskTOMLMonitor`] without a base
impl OnDiskTomlMonitor<NopMonitor> {
/// Create new [`OnDiskTomlMonitor`] without a base
#[must_use]
pub fn nop<P>(filename: P) -> Self
where
@ -155,8 +155,8 @@ impl OnDiskTOMLMonitor<NopMonitor> {
}
#[derive(Debug, Clone)]
/// Wraps a base monitor and continuously appends the current statistics to a JSON lines file.
pub struct OnDiskJSONMonitor<F, M>
/// Wraps a base monitor and continuously appends the current statistics to a Json lines file.
pub struct OnDiskJsonMonitor<F, M>
where
F: FnMut(&mut M) -> bool,
M: Monitor,
@ -167,12 +167,12 @@ where
log_record: F,
}
impl<F, M> OnDiskJSONMonitor<F, M>
impl<F, M> OnDiskJsonMonitor<F, M>
where
F: FnMut(&mut M) -> bool,
M: Monitor,
{
/// Create a new [`OnDiskJSONMonitor`]
/// Create a new [`OnDiskJsonMonitor`]
pub fn new<P>(filename: P, base: M, log_record: F) -> Self
where
P: Into<PathBuf>,
@ -187,7 +187,7 @@ where
}
}
impl<F, M> Monitor for OnDiskJSONMonitor<F, M>
impl<F, M> Monitor for OnDiskJsonMonitor<F, M>
where
F: FnMut(&mut M) -> bool,
M: Monitor,
@ -225,7 +225,7 @@ where
"exec_sec": self.base.execs_per_sec(),
"client_stats": self.client_stats(),
});
writeln!(&file, "{line}").expect("Unable to write JSON to file");
writeln!(&file, "{line}").expect("Unable to write Json to file");
}
self.base.display(event_msg, sender_id);
}

View File

@ -4,7 +4,6 @@ pub mod multi;
pub use multi::MultiMonitor;
#[cfg(all(feature = "tui_monitor", feature = "std"))]
#[allow(missing_docs)]
pub mod tui;
#[cfg(all(feature = "prometheus_monitor", feature = "std"))]
@ -20,7 +19,7 @@ use alloc::{borrow::Cow, fmt::Debug, string::String, vec::Vec};
use core::{fmt, fmt::Write, time::Duration};
#[cfg(feature = "std")]
pub use disk::{OnDiskJSONMonitor, OnDiskTOMLMonitor};
pub use disk::{OnDiskJsonMonitor, OnDiskTomlMonitor};
use hashbrown::HashMap;
use libafl_bolts::{current_time, format_duration_hms, ClientId};
use serde::{Deserialize, Serialize};

View File

@ -1,26 +1,31 @@
// ===== overview for prommon =====
// The client (i.e., the fuzzer) sets up an HTTP endpoint (/metrics).
// The endpoint contains metrics such as execution rate.
// A prometheus server (can use a precompiled binary or docker) then scrapes \
// the endpoint at regular intervals (configurable via prometheus.yml file).
// ====================
//
// == how to use it ===
// This monitor should plug into any fuzzer similar to other monitors.
// In your fuzzer, include:
// ```rust,ignore
// use libafl::monitors::PrometheusMonitor;
// ```
// as well as:
// ```rust,ignore
// let listener = "127.0.0.1:8080".to_string(); // point prometheus to scrape here in your prometheus.yml
// let mon = PrometheusMonitor::new(listener, |s| log::info!("{s}"));
// and then like with any other monitor, pass it into the event manager like so:
// let mut mgr = SimpleEventManager::new(mon);
// ```
// When using docker, you may need to point prometheus.yml to the docker0 interface or host.docker.internal
// ====================
//! Prometheus Monitor to log to a prometheus endpoint.
//!
//! ## Overview
//!
//! The client (i.e., the fuzzer) sets up an HTTP endpoint (/metrics).
//! The endpoint contains metrics such as execution rate.
//!
//! A prometheus server (can use a precompiled binary or docker) then scrapes \
//! the endpoint at regular intervals (configurable via prometheus.yml file).
//!
//! ## How to use it
//!
//! This monitor should plug into any fuzzer similar to other monitors.
//! In your fuzzer:
//!
//! ```rust
//! // First, include:
//! use libafl::monitors::PrometheusMonitor;
//!
//! // Then, create the monitor:
//! let listener = "127.0.0.1:8080".to_string(); // point prometheus to scrape here in your prometheus.yml
//! let mon = PrometheusMonitor::new(listener, |s| log::info!("{s}"));
//!
//! // and finally, like with any other monitor, pass it into the event manager like so:
//! // let mgr = SimpleEventManager::new(mon);
//! ```
//!
//! When using docker, you may need to point `prometheus.yml` to the `docker0` interface or `host.docker.internal`
use alloc::{borrow::Cow, fmt::Debug, string::String, vec::Vec};
use core::{fmt, time::Duration};

View File

@ -1,4 +1,4 @@
//! Monitor based on ratatui
//! Fancy-looking terminal UI monitor, similar to AFL, based on [ratatui](https://ratatui.rs/)
use alloc::{borrow::Cow, boxed::Box, string::ToString};
use core::cmp;
@ -24,30 +24,60 @@ use hashbrown::HashMap;
use libafl_bolts::{current_time, format_duration_hms, ClientId};
use ratatui::{backend::CrosstermBackend, Terminal};
use serde_json::Value;
use typed_builder::TypedBuilder;
#[cfg(feature = "introspection")]
use super::{ClientPerfMonitor, PerfFeature};
use crate::monitors::{Aggregator, AggregatorOps, ClientStats, Monitor, UserStats, UserStatsValue};
#[allow(missing_docs)]
pub mod ui;
use ui::TuiUI;
use ui::TuiUi;
const DEFAULT_TIME_WINDOW: u64 = 60 * 10; // 10 min
const DEFAULT_LOGS_NUMBER: usize = 128;
#[derive(Debug, Clone, TypedBuilder)]
#[builder(build_method(into = TuiMonitor), builder_method(vis = "pub(crate)",
doc = "Build the [`TuiMonitor`] from the set values"))]
/// Settings to create a new [`TuiMonitor`].
/// Use `TuiMonitor::builder()` or create this config and call `.into()` to create a new [`TuiMonitor`].
pub struct TuiMonitorConfig {
/// The title to show
#[builder(default_code = r#""LibAFL Fuzzer".to_string()"#, setter(into))]
pub title: String,
/// A version string to show for this (optional)
#[builder(default_code = r#""default".to_string()"#, setter(into))]
pub version: String,
/// Creates the monitor with an explicit `start_time`.
/// If nothings was set, this will use [`current_time`] instead.
#[builder(default_code = "current_time()")]
pub start_time: Duration,
/// Enables unicode TUI graphics, Looks better but may interfere with old terminals.
#[builder(default = true)]
pub enhanced_graphics: bool,
}
/// A single status entry for timings
#[derive(Debug, Copy, Clone)]
pub struct TimedStat {
/// The time
pub time: Duration,
/// The item
pub item: u64,
}
/// Stats for timings
#[derive(Debug, Clone)]
pub struct TimedStats {
/// Series of [`TimedStat`] entries
pub series: VecDeque<TimedStat>,
/// The time window to keep track of
pub window: Duration,
}
impl TimedStats {
/// Create a new [`TimedStats`] struct
#[must_use]
pub fn new(window: Duration) -> Self {
Self {
@ -56,6 +86,7 @@ impl TimedStats {
}
}
/// Add a stat datapoint
pub fn add(&mut self, time: Duration, item: u64) {
if self.series.is_empty() || self.series.back().unwrap().item != item {
if self.series.front().is_some()
@ -67,6 +98,7 @@ impl TimedStats {
}
}
/// Add a stat datapoint for the `current_time`
pub fn add_now(&mut self, item: u64) {
if self.series.is_empty() || self.series[self.series.len() - 1].item != item {
let time = current_time();
@ -79,6 +111,7 @@ impl TimedStats {
}
}
/// Change the window duration
pub fn update_window(&mut self, window: Duration) {
self.window = window;
while !self.series.is_empty()
@ -89,6 +122,7 @@ impl TimedStats {
}
}
/// The context to show performance metrics
#[cfg(feature = "introspection")]
#[derive(Debug, Default, Clone)]
pub struct PerfTuiContext {
@ -101,6 +135,7 @@ pub struct PerfTuiContext {
#[cfg(feature = "introspection")]
impl PerfTuiContext {
/// Get the data for performance metrics
#[allow(clippy::cast_precision_loss)]
pub fn grab_data(&mut self, m: &ClientPerfMonitor) {
// Calculate the elapsed time from the monitor
@ -164,15 +199,21 @@ impl PerfTuiContext {
}
}
/// Data struct to process timings
#[derive(Debug, Default, Clone)]
pub struct ProcessTiming {
/// The start time
pub client_start_time: Duration,
/// The executions speed
pub exec_speed: String,
/// Timing of the last new corpus entry
pub last_new_entry: Duration,
/// Timing of the last new solution
pub last_saved_solution: Duration,
}
impl ProcessTiming {
/// Create a new [`ProcessTiming`] struct
fn new() -> Self {
Self {
exec_speed: "0".to_string(),
@ -181,6 +222,8 @@ impl ProcessTiming {
}
}
/// The geometry of a single data point
#[allow(missing_docs)]
#[derive(Debug, Default, Clone)]
pub struct ItemGeometry {
pub pending: u64,
@ -199,6 +242,8 @@ impl ItemGeometry {
}
}
/// The context for a single client tracked in this [`TuiMonitor`]
#[allow(missing_docs)]
#[derive(Debug, Default, Clone)]
pub struct ClientTuiContext {
pub corpus: u64,
@ -215,6 +260,7 @@ pub struct ClientTuiContext {
}
impl ClientTuiContext {
/// Grab data for a single client
pub fn grab_data(&mut self, client: &ClientStats, exec_sec: String) {
self.corpus = client.corpus_size;
self.objectives = client.objective_size;
@ -267,6 +313,8 @@ impl ClientTuiContext {
}
}
/// The [`TuiContext`] for this [`TuiMonitor`]
#[allow(missing_docs)]
#[derive(Debug, Clone)]
pub struct TuiContext {
pub graphs: Vec<String>,
@ -326,7 +374,7 @@ impl TuiContext {
}
}
/// Tracking monitor during fuzzing and display with ratatui
/// Tracking monitor during fuzzing and display with [`ratatui`](https://ratatui.rs/)
#[derive(Debug, Clone)]
pub struct TuiMonitor {
pub(crate) context: Arc<RwLock<TuiContext>>,
@ -336,6 +384,16 @@ pub struct TuiMonitor {
aggregator: Aggregator,
}
impl From<TuiMonitorConfig> for TuiMonitor {
#[allow(deprecated)]
fn from(builder: TuiMonitorConfig) -> Self {
Self::with_time(
TuiUi::with_version(builder.title, builder.version, builder.enhanced_graphics),
builder.start_time,
)
}
}
impl Monitor for TuiMonitor {
/// The client monitor, mutable
/// This also includes disabled "padding" clients.
@ -443,15 +501,35 @@ impl Monitor for TuiMonitor {
}
impl TuiMonitor {
/// Creates the monitor
/// Create a builder for [`TuiMonitor`]
pub fn builder() -> TuiMonitorConfigBuilder {
TuiMonitorConfig::builder()
}
/// Creates the monitor.
///
/// # Deprecation Note
/// Use `TuiMonitor::builder()` instead.
#[deprecated(
since = "0.13.2",
note = "Please use TuiMonitor::builder() instead of creating TuiUi directly."
)]
#[must_use]
pub fn new(tui_ui: TuiUI) -> Self {
#[allow(deprecated)]
pub fn new(tui_ui: TuiUi) -> Self {
Self::with_time(tui_ui, current_time())
}
/// Creates the monitor with a given `start_time`.
///
/// # Deprecation Note
/// Use `TuiMonitor::builder()` instead.
#[deprecated(
since = "0.13.2",
note = "Please use TuiMonitor::builder() instead of creating TuiUi directly."
)]
#[must_use]
pub fn with_time(tui_ui: TuiUI, start_time: Duration) -> Self {
pub fn with_time(tui_ui: TuiUi, start_time: Duration) -> Self {
let context = Arc::new(RwLock::new(TuiContext::new(start_time)));
enable_raw_mode().unwrap();
@ -565,7 +643,7 @@ impl TuiMonitor {
fn run_tui_thread<W: Write + Send + Sync + 'static>(
context: Arc<RwLock<TuiContext>>,
tick_rate: Duration,
tui_ui: TuiUI,
tui_ui: TuiUi,
stdout_provider: impl Send + Sync + 'static + Fn() -> W,
) {
thread::spawn(move || -> io::Result<()> {

View File

@ -21,7 +21,7 @@ use super::{
};
#[derive(Default, Debug)]
pub struct TuiUI {
pub struct TuiUi {
title: String,
version: String,
enhanced_graphics: bool,
@ -34,13 +34,13 @@ pub struct TuiUI {
pub should_quit: bool,
}
impl TuiUI {
impl TuiUi {
#[must_use]
pub fn new(title: String, enhanced_graphics: bool) -> Self {
Self::with_version(title, String::from("default"), enhanced_graphics)
}
// create the TuiUI with a given `version`.
// create the TuiUi with a given `version`.
#[must_use]
pub fn with_version(title: String, version: String, enhanced_graphics: bool) -> Self {
Self {
@ -49,7 +49,7 @@ impl TuiUI {
enhanced_graphics,
show_logs: true,
clients_idx: 1,
..TuiUI::default()
..TuiUi::default()
}
}
pub fn on_key(&mut self, c: char) {

View File

@ -18,10 +18,7 @@ use libafl::{
},
executors::ExitKind,
inputs::UsesInput,
monitors::{
tui::{ui::TuiUI, TuiMonitor},
Monitor, MultiMonitor,
},
monitors::{tui::TuiMonitor, Monitor, MultiMonitor},
stages::{HasCurrentStage, StagesTuple},
state::{HasExecutions, HasLastReportTime, HasSolutions, Stoppable, UsesState},
Error, Fuzzer, HasMetadata,
@ -208,7 +205,10 @@ pub fn fuzz(
if let Some(forks) = options.forks() {
let shmem_provider = StdShMemProvider::new().expect("Failed to init shared memory");
if options.tui() {
let monitor = TuiMonitor::new(TuiUI::new(options.fuzzer_name().to_string(), true));
let monitor = TuiMonitor::builder()
.title(options.fuzzer_name())
.enhanced_graphics(true)
.build();
fuzz_many_forking(options, harness, shmem_provider, forks, monitor)
} else if forks == 1 {
let monitor = MultiMonitor::with_time(
@ -227,7 +227,10 @@ pub fn fuzz(
// if the user specifies TUI, we assume they want to fork; it would not be possible to use
// TUI safely otherwise
let shmem_provider = StdShMemProvider::new().expect("Failed to init shared memory");
let monitor = TuiMonitor::new(TuiUI::new(options.fuzzer_name().to_string(), true));
let monitor = TuiMonitor::builder()
.title(options.fuzzer_name())
.enhanced_graphics(true)
.build();
fuzz_many_forking(options, harness, shmem_provider, 1, monitor)
} else {
destroy_output_fds(options);

View File

@ -35,6 +35,8 @@ for task in output[
print(os.environ)
if "libafl_frida" in task:
# DOCS_RS is needed for libafl_frida to build without auto-download feature
cargo_check = subprocess.check_output(task, shell=True, text=True, env=dict(os.environ, DOCS_RS="1"))
cargo_check = subprocess.check_output(
task, shell=True, text=True, env=dict(os.environ, DOCS_RS="1")
)
else:
cargo_check = subprocess.check_output(task, shell=True, text=True)
cargo_check = subprocess.check_output(task, shell=True, text=True)