libafl-fuzz: introduce nyx_mode (#2503)
* add nyx_mode * fix frida ci? * damn clippy * clippy
This commit is contained in:
parent
f7f8dff6cd
commit
87f5f21e01
@ -31,6 +31,7 @@ memmap2 = "0.9.4"
|
|||||||
nix = { version = "0.29.0", features = ["fs"] }
|
nix = { version = "0.29.0", features = ["fs"] }
|
||||||
regex = "1.10.5"
|
regex = "1.10.5"
|
||||||
serde = { version = "1.0.117", features = ["derive"] }
|
serde = { version = "1.0.117", features = ["derive"] }
|
||||||
|
libafl_nyx = { path = "../../../libafl_nyx" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["track_hit_feedbacks"]
|
default = ["track_hit_feedbacks"]
|
||||||
|
@ -226,6 +226,36 @@ test -n "$( ls ./test/output-unicorn-cmpcov/fuzzer_main/queue/id:000002* 2>/dev/
|
|||||||
'''
|
'''
|
||||||
dependencies = ["build_libafl_fuzz", "build_afl", "build_unicorn_mode"]
|
dependencies = ["build_libafl_fuzz", "build_afl", "build_unicorn_mode"]
|
||||||
|
|
||||||
|
[tasks.test_nyx_mode]
|
||||||
|
script_runner = "@shell"
|
||||||
|
script = '''
|
||||||
|
export AFL_PATH=${AFL_DIR}
|
||||||
|
export AFL_CORES=0
|
||||||
|
export AFL_STATS_INTERVAL=1
|
||||||
|
export AFL_DEBUG=1
|
||||||
|
export LIBAFL_DEBUG_OUTPUT=1
|
||||||
|
AFL_PATH=${AFL_DIR} ${AFL_CC_PATH} ./test/test-instr.c -o ./test/out-instr
|
||||||
|
rm -rf ./test/nyx-test
|
||||||
|
cd ../../../libafl_nyx
|
||||||
|
rm -rf packer
|
||||||
|
git clone https://github.com/nyx-fuzz/packer.git
|
||||||
|
python3 packer/packer/nyx_packer.py \
|
||||||
|
../fuzzers/forkserver/libafl-fuzz/test/out-instr \
|
||||||
|
../fuzzers/forkserver/libafl-fuzz/test/out-nyx \
|
||||||
|
afl \
|
||||||
|
instrumentation \
|
||||||
|
--fast_reload_mode \
|
||||||
|
--purge
|
||||||
|
python3 packer/packer/nyx_config_gen.py ../fuzzers/forkserver/libafl-fuzz/test/out-nyx Kernel
|
||||||
|
cd ../fuzzers/forkserver/libafl-fuzz/
|
||||||
|
timeout 15s ${FUZZER} -i ./test/seeds_nyx -o ./test/output-nyx -X -- ./test/out-nyx
|
||||||
|
test -n "$( ls ./test/output-nyx/fuzzer_main/queue/id:000003* 2>/dev/null )" || {
|
||||||
|
echo "No new corpus entries found for Nyx mode!"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
'''
|
||||||
|
dependencies = ["build_afl", "build_libafl_fuzz"]
|
||||||
|
|
||||||
[tasks.clean]
|
[tasks.clean]
|
||||||
linux_alias = "clean_unix"
|
linux_alias = "clean_unix"
|
||||||
mac_alias = "clean_unix"
|
mac_alias = "clean_unix"
|
||||||
|
@ -1,10 +1,17 @@
|
|||||||
use std::{
|
use std::{
|
||||||
fs::File,
|
fs::File,
|
||||||
|
marker::PhantomData,
|
||||||
os::unix::fs::PermissionsExt,
|
os::unix::fs::PermissionsExt,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
};
|
};
|
||||||
|
|
||||||
use libafl::Error;
|
use libafl::{
|
||||||
|
executors::{Executor, ExitKind, HasObservers, HasTimeout},
|
||||||
|
observers::ObserversTuple,
|
||||||
|
state::{State, UsesState},
|
||||||
|
Error,
|
||||||
|
};
|
||||||
|
use libafl_bolts::tuples::RefIndexable;
|
||||||
use memmap2::{Mmap, MmapOptions};
|
use memmap2::{Mmap, MmapOptions};
|
||||||
use nix::libc::{S_IRUSR, S_IXUSR};
|
use nix::libc::{S_IRUSR, S_IXUSR};
|
||||||
|
|
||||||
@ -244,3 +251,87 @@ fn check_file_found(file: &Path, perm: u32) -> bool {
|
|||||||
}
|
}
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum SupportedExecutors<S, OT, FSV, NYX> {
|
||||||
|
Forkserver(FSV, PhantomData<(S, OT)>),
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
Nyx(NYX),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S, OT, FSV, NYX> UsesState for SupportedExecutors<S, OT, FSV, NYX>
|
||||||
|
where
|
||||||
|
S: State,
|
||||||
|
{
|
||||||
|
type State = S;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S, OT, FSV, NYX, EM, Z> Executor<EM, Z> for SupportedExecutors<S, OT, FSV, NYX>
|
||||||
|
where
|
||||||
|
S: State,
|
||||||
|
Z: UsesState<State = S>,
|
||||||
|
EM: UsesState<State = S>,
|
||||||
|
FSV: Executor<EM, Z, State = S>,
|
||||||
|
NYX: Executor<EM, Z, State = S>,
|
||||||
|
{
|
||||||
|
fn run_target(
|
||||||
|
&mut self,
|
||||||
|
fuzzer: &mut Z,
|
||||||
|
state: &mut S,
|
||||||
|
mgr: &mut EM,
|
||||||
|
input: &S::Input,
|
||||||
|
) -> Result<ExitKind, Error> {
|
||||||
|
match self {
|
||||||
|
Self::Forkserver(fsrv, _) => fsrv.run_target(fuzzer, state, mgr, input),
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
Self::Nyx(nyx) => nyx.run_target(fuzzer, state, mgr, input),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S, OT, FSV, NYX> HasObservers for SupportedExecutors<S, OT, FSV, NYX>
|
||||||
|
where
|
||||||
|
OT: ObserversTuple<S::Input, S>,
|
||||||
|
S: State,
|
||||||
|
FSV: HasObservers<Observers = OT>,
|
||||||
|
NYX: HasObservers<Observers = OT>,
|
||||||
|
{
|
||||||
|
type Observers = OT;
|
||||||
|
#[inline]
|
||||||
|
fn observers(&self) -> RefIndexable<&Self::Observers, Self::Observers> {
|
||||||
|
match self {
|
||||||
|
Self::Forkserver(fsrv, _) => fsrv.observers(),
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
Self::Nyx(nyx) => nyx.observers(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn observers_mut(&mut self) -> RefIndexable<&mut Self::Observers, Self::Observers> {
|
||||||
|
match self {
|
||||||
|
Self::Forkserver(fsrv, _) => fsrv.observers_mut(),
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
Self::Nyx(nyx) => nyx.observers_mut(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S, OT, FSV, NYX> HasTimeout for SupportedExecutors<S, OT, FSV, NYX>
|
||||||
|
where
|
||||||
|
FSV: HasTimeout,
|
||||||
|
NYX: HasTimeout,
|
||||||
|
{
|
||||||
|
fn set_timeout(&mut self, timeout: std::time::Duration) {
|
||||||
|
match self {
|
||||||
|
Self::Forkserver(fsrv, _) => fsrv.set_timeout(timeout),
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
Self::Nyx(nyx) => nyx.set_timeout(timeout),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn timeout(&self) -> std::time::Duration {
|
||||||
|
match self {
|
||||||
|
Self::Forkserver(fsrv, _) => fsrv.timeout(),
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
Self::Nyx(nyx) => nyx.timeout(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -49,13 +49,14 @@ use libafl_bolts::{
|
|||||||
tuples::{tuple_list, Handled, Merge},
|
tuples::{tuple_list, Handled, Merge},
|
||||||
AsSliceMut,
|
AsSliceMut,
|
||||||
};
|
};
|
||||||
|
use libafl_nyx::{executor::NyxExecutor, helper::NyxHelper, settings::NyxSettings};
|
||||||
use libafl_targets::{cmps::AFLppCmpLogMap, AFLppCmpLogObserver, AFLppCmplogTracingStage};
|
use libafl_targets::{cmps::AFLppCmpLogMap, AFLppCmpLogObserver, AFLppCmplogTracingStage};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
corpus::{set_corpus_filepath, set_solution_filepath},
|
corpus::{set_corpus_filepath, set_solution_filepath},
|
||||||
env_parser::AFL_DEFAULT_MAP_SIZE,
|
env_parser::AFL_DEFAULT_MAP_SIZE,
|
||||||
executor::find_afl_binary,
|
executor::{find_afl_binary, SupportedExecutors},
|
||||||
feedback::{
|
feedback::{
|
||||||
filepath::CustomFilepathToTestcaseFeedback, persistent_record::PersitentRecordFeedback,
|
filepath::CustomFilepathToTestcaseFeedback, persistent_record::PersitentRecordFeedback,
|
||||||
seed::SeedFeedback,
|
seed::SeedFeedback,
|
||||||
@ -94,10 +95,38 @@ where
|
|||||||
shmem.write_to_env(SHMEM_ENV_VAR).unwrap();
|
shmem.write_to_env(SHMEM_ENV_VAR).unwrap();
|
||||||
let shmem_buf = shmem.as_slice_mut();
|
let shmem_buf = shmem.as_slice_mut();
|
||||||
|
|
||||||
// Create an observation channel to keep track of edges hit.
|
// If we are in Nyx Mode, we need to use a different map observer.
|
||||||
let edges_observer = unsafe {
|
#[cfg(target_os = "linux")]
|
||||||
HitcountsMapObserver::new(StdMapObserver::new("edges", shmem_buf)).track_indices()
|
let (nyx_helper, edges_observer) = {
|
||||||
|
if opt.nyx_mode {
|
||||||
|
// main node is the first core id in CentralizedLauncher
|
||||||
|
let cores = opt.cores.clone().expect("invariant; should never occur");
|
||||||
|
let main_node_core_id = match cores.ids.len() {
|
||||||
|
1 => None,
|
||||||
|
_ => Some(cores.ids.first().expect("invariant; should never occur").0),
|
||||||
};
|
};
|
||||||
|
let nyx_settings = NyxSettings::builder()
|
||||||
|
.cpu_id(core_id.0)
|
||||||
|
.parent_cpu_id(main_node_core_id)
|
||||||
|
.build();
|
||||||
|
let nyx_helper = NyxHelper::new(opt.executable.clone(), nyx_settings).unwrap();
|
||||||
|
let observer = unsafe {
|
||||||
|
StdMapObserver::from_mut_ptr(
|
||||||
|
"edges",
|
||||||
|
nyx_helper.bitmap_buffer,
|
||||||
|
nyx_helper.bitmap_size,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
(Some(nyx_helper), observer)
|
||||||
|
} else {
|
||||||
|
let observer = unsafe { StdMapObserver::new("edges", shmem_buf) };
|
||||||
|
(None, observer)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#[cfg(not(target_os = "linux"))]
|
||||||
|
let edges_observer = { unsafe { StdMapObserver::new("edges", shmem_buf) } };
|
||||||
|
|
||||||
|
let edges_observer = HitcountsMapObserver::new(edges_observer).track_indices();
|
||||||
|
|
||||||
// Create a MapFeedback for coverage guided fuzzin'
|
// Create a MapFeedback for coverage guided fuzzin'
|
||||||
let map_feedback = MaxMapFeedback::new(&edges_observer);
|
let map_feedback = MaxMapFeedback::new(&edges_observer);
|
||||||
@ -261,9 +290,17 @@ where
|
|||||||
std::env::set_var("LD_PRELOAD", &preload);
|
std::env::set_var("LD_PRELOAD", &preload);
|
||||||
std::env::set_var("DYLD_INSERT_LIBRARIES", &preload);
|
std::env::set_var("DYLD_INSERT_LIBRARIES", &preload);
|
||||||
}
|
}
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
let mut executor = {
|
||||||
|
if opt.nyx_mode {
|
||||||
|
SupportedExecutors::Nyx(NyxExecutor::builder().build(
|
||||||
|
nyx_helper.unwrap(),
|
||||||
|
(edges_observer, tuple_list!(time_observer)),
|
||||||
|
))
|
||||||
|
} else {
|
||||||
// Create the base Executor
|
// Create the base Executor
|
||||||
let mut executor_builder = base_executor_builder(opt, &mut shmem_provider, fuzzer_dir);
|
let mut executor_builder =
|
||||||
|
base_forkserver_builder(opt, &mut shmem_provider, fuzzer_dir);
|
||||||
// Set a custom exit code to be interpreted as a Crash if configured.
|
// Set a custom exit code to be interpreted as a Crash if configured.
|
||||||
if let Some(crash_exitcode) = opt.crash_exitcode {
|
if let Some(crash_exitcode) = opt.crash_exitcode {
|
||||||
executor_builder = executor_builder.crash_exitcode(crash_exitcode);
|
executor_builder = executor_builder.crash_exitcode(crash_exitcode);
|
||||||
@ -275,9 +312,36 @@ where
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Finalize and build our Executor
|
// Finalize and build our Executor
|
||||||
let mut executor = executor_builder
|
SupportedExecutors::Forkserver(
|
||||||
|
executor_builder
|
||||||
.build_dynamic_map(edges_observer, tuple_list!(time_observer))
|
.build_dynamic_map(edges_observer, tuple_list!(time_observer))
|
||||||
.unwrap();
|
.unwrap(),
|
||||||
|
PhantomData,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#[cfg(not(target_os = "linux"))]
|
||||||
|
let executor = {
|
||||||
|
// Create the base Executor
|
||||||
|
let mut executor_builder = base_forkserver_builder(opt, &mut shmem_provider, fuzzer_dir);
|
||||||
|
// Set a custom exit code to be interpreted as a Crash if configured.
|
||||||
|
if let Some(crash_exitcode) = opt.crash_exitcode {
|
||||||
|
executor_builder = executor_builder.crash_exitcode(crash_exitcode);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable autodict if configured
|
||||||
|
if !opt.no_autodict {
|
||||||
|
executor_builder = executor_builder.autotokens(&mut tokens);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Finalize and build our Executor
|
||||||
|
SupportedExecutors::Forkserver(
|
||||||
|
executor_builder
|
||||||
|
.build_dynamic_map(edges_observer, tuple_list!(time_observer))
|
||||||
|
.unwrap(),
|
||||||
|
PhantomData,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
let queue_dir = fuzzer_dir.join("queue");
|
let queue_dir = fuzzer_dir.join("queue");
|
||||||
if opt.auto_resume {
|
if opt.auto_resume {
|
||||||
@ -383,7 +447,7 @@ where
|
|||||||
|
|
||||||
// Create the CmpLog executor.
|
// Create the CmpLog executor.
|
||||||
// Cmplog has 25% execution overhead so we give it double the timeout
|
// Cmplog has 25% execution overhead so we give it double the timeout
|
||||||
let cmplog_executor = base_executor_builder(opt, &mut shmem_provider, fuzzer_dir)
|
let cmplog_executor = base_forkserver_builder(opt, &mut shmem_provider, fuzzer_dir)
|
||||||
.timeout(Duration::from_millis(opt.hang_timeout * 2))
|
.timeout(Duration::from_millis(opt.hang_timeout * 2))
|
||||||
.program(cmplog_executable_path)
|
.program(cmplog_executable_path)
|
||||||
.build(tuple_list!(cmplog_observer))
|
.build(tuple_list!(cmplog_observer))
|
||||||
@ -458,7 +522,7 @@ where
|
|||||||
// TODO: serialize state when exiting.
|
// TODO: serialize state when exiting.
|
||||||
}
|
}
|
||||||
|
|
||||||
fn base_executor_builder<'a>(
|
fn base_forkserver_builder<'a>(
|
||||||
opt: &'a Opt,
|
opt: &'a Opt,
|
||||||
shmem_provider: &'a mut UnixShMemProvider,
|
shmem_provider: &'a mut UnixShMemProvider,
|
||||||
fuzzer_dir: &Path,
|
fuzzer_dir: &Path,
|
||||||
@ -475,6 +539,9 @@ fn base_executor_builder<'a>(
|
|||||||
if let Some(target_env) = &opt.target_env {
|
if let Some(target_env) = &opt.target_env {
|
||||||
executor = executor.envs(target_env);
|
executor = executor.envs(target_env);
|
||||||
}
|
}
|
||||||
|
if opt.frida_mode {
|
||||||
|
executor = executor.kill_signal(nix::sys::signal::Signal::SIGKILL);
|
||||||
|
}
|
||||||
if let Some(kill_signal) = opt.kill_signal {
|
if let Some(kill_signal) = opt.kill_signal {
|
||||||
executor = executor.kill_signal(kill_signal);
|
executor = executor.kill_signal(kill_signal);
|
||||||
}
|
}
|
||||||
|
@ -297,7 +297,7 @@ struct Opt {
|
|||||||
#[arg(short = 'Q')]
|
#[arg(short = 'Q')]
|
||||||
qemu_mode: bool,
|
qemu_mode: bool,
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
#[clap(skip)]
|
#[arg(short = 'X')]
|
||||||
nyx_mode: bool,
|
nyx_mode: bool,
|
||||||
/// use unicorn-based instrumentation (Unicorn mode)
|
/// use unicorn-based instrumentation (Unicorn mode)
|
||||||
#[arg(short = 'U')]
|
#[arg(short = 'U')]
|
||||||
|
@ -870,6 +870,7 @@ impl<'a, T> From<&'a mut &'a mut [T]> for OwnedMutSlice<'a, T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Wrap a mutable slice and convert to a Box on serialize.
|
/// Wrap a mutable slice and convert to a Box on serialize.
|
||||||
|
///
|
||||||
/// We use a hidden inner enum so the public API can be safe,
|
/// We use a hidden inner enum so the public API can be safe,
|
||||||
/// unless the user uses the unsafe [`OwnedMutSizedSlice::from_raw_mut`].
|
/// unless the user uses the unsafe [`OwnedMutSizedSlice::from_raw_mut`].
|
||||||
/// The variable length version is [`OwnedMutSlice`].
|
/// The variable length version is [`OwnedMutSlice`].
|
||||||
|
@ -20,7 +20,7 @@ categories = [
|
|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[target.'cfg(target_os = "linux")'.dependencies]
|
[target.'cfg(target_os = "linux")'.dependencies]
|
||||||
libnyx = { git = "https://github.com/nyx-fuzz/libnyx.git", rev = "6833d236dfe785a8a23d8c8d79e74c99fa635004" }
|
libnyx = { git = "https://github.com/nyx-fuzz/libnyx.git", rev = "ea6ceb994ab975b81aea0daaf64b92a3066c1e8d" }
|
||||||
libafl = { path = "../libafl", version = "0.13.2", features = [
|
libafl = { path = "../libafl", version = "0.13.2", features = [
|
||||||
"std",
|
"std",
|
||||||
"libafl_derive",
|
"libafl_derive",
|
||||||
|
@ -5,7 +5,7 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use libafl::{
|
use libafl::{
|
||||||
executors::{Executor, ExitKind, HasObservers},
|
executors::{Executor, ExitKind, HasObservers, HasTimeout},
|
||||||
inputs::HasTargetBytes,
|
inputs::HasTargetBytes,
|
||||||
observers::{ObserversTuple, StdOutObserver},
|
observers::{ObserversTuple, StdOutObserver},
|
||||||
state::{HasExecutions, State, UsesState},
|
state::{HasExecutions, State, UsesState},
|
||||||
@ -129,6 +129,28 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<S, OT> HasTimeout for NyxExecutor<S, OT> {
|
||||||
|
fn timeout(&self) -> std::time::Duration {
|
||||||
|
self.helper.timeout
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_timeout(&mut self, timeout: std::time::Duration) {
|
||||||
|
let micros = 1000000;
|
||||||
|
let mut timeout_secs = timeout.as_secs();
|
||||||
|
let mut timeout_micros = timeout.as_micros() - u128::from(timeout.as_secs() * micros);
|
||||||
|
// since timeout secs is a u8 -> convert any overflow into micro secs
|
||||||
|
if timeout_secs > 255 {
|
||||||
|
timeout_micros = u128::from((timeout_secs - 255) * micros);
|
||||||
|
timeout_secs = 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.helper.timeout = timeout;
|
||||||
|
|
||||||
|
self.helper
|
||||||
|
.set_timeout(timeout_secs as u8, timeout_micros as u32);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<S, OT> NyxExecutor<S, OT> {
|
impl<S, OT> NyxExecutor<S, OT> {
|
||||||
/// Convert `trace_bits` ptr into real trace map
|
/// Convert `trace_bits` ptr into real trace map
|
||||||
///
|
///
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/// [`NyxHelper`] is used to wrap `NyxProcess`
|
/// [`NyxHelper`] is used to wrap `NyxProcess`
|
||||||
use std::{fmt::Debug, fs::File, path::Path};
|
use std::{fmt::Debug, fs::File, path::Path, time::Duration};
|
||||||
|
|
||||||
use libafl::Error;
|
use libafl::Error;
|
||||||
use libnyx::{NyxConfig, NyxProcess, NyxProcessRole};
|
use libnyx::{NyxConfig, NyxProcess, NyxProcessRole};
|
||||||
@ -10,6 +10,8 @@ pub struct NyxHelper {
|
|||||||
pub nyx_process: NyxProcess,
|
pub nyx_process: NyxProcess,
|
||||||
pub nyx_stdout: File,
|
pub nyx_stdout: File,
|
||||||
|
|
||||||
|
pub timeout: Duration,
|
||||||
|
|
||||||
pub bitmap_size: usize,
|
pub bitmap_size: usize,
|
||||||
pub bitmap_buffer: *mut u8,
|
pub bitmap_buffer: *mut u8,
|
||||||
}
|
}
|
||||||
@ -66,12 +68,10 @@ impl NyxHelper {
|
|||||||
let bitmap_size = nyx_process.bitmap_buffer_size();
|
let bitmap_size = nyx_process.bitmap_buffer_size();
|
||||||
let bitmap_buffer = nyx_process.bitmap_buffer_mut().as_mut_ptr();
|
let bitmap_buffer = nyx_process.bitmap_buffer_mut().as_mut_ptr();
|
||||||
|
|
||||||
Ok(Self {
|
let mut timeout = Duration::from_secs(u64::from(settings.timeout_secs));
|
||||||
nyx_process,
|
timeout += Duration::from_micros(u64::from(settings.timeout_micro_secs));
|
||||||
nyx_stdout,
|
|
||||||
bitmap_size,
|
Ok(Self { nyx_process, nyx_stdout, timeout, bitmap_size, bitmap_buffer })
|
||||||
bitmap_buffer,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a timeout for Nyx.
|
/// Set a timeout for Nyx.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user