#![no_main]
use arbitrary::{Arbitrary, Unstructured};
use commonware_cryptography::{sha256, Sha256};
use commonware_runtime::{buffer::PoolRef, deterministic, Runner, RwLock};
use commonware_storage::{
adb::{
any::fixed::{unordered::Any, Config as AnyConfig},
sync::{self, engine::Config as EngineConfig, Target},
},
mmr::{Location, StandardHasher, MAX_LOCATION},
translator::TwoCap,
};
use core::num::{NonZeroU64, NonZeroUsize};
use libfuzzer_sys::fuzz_target;
use std::sync::Arc;
type TestDb = Any<deterministic::Context, sha256::Digest, sha256::Digest, Sha256, TwoCap>;
#[derive(Arbitrary, Clone)]
struct FuzzInput {
partition_suffix: u64,
start_offset: u16,
extra_batch: u16,
max_outstanding: u8,
apply_batch: u16,
log_items_per_blob: u16,
mmr_items_per_blob: u16,
log_write_buffer: u16,
mmr_write_buffer: u16,
pool_page_size: u16,
pool_capacity: u16,
}
fuzz_target!(|data: &[u8]| {
let mut unstructured = Unstructured::new(data);
let Ok(params) = FuzzInput::arbitrary(&mut unstructured) else {
return;
};
let runner = deterministic::Runner::default();
runner.start(|context| {
let input = params.clone();
async move {
let FuzzInput {
partition_suffix,
start_offset,
extra_batch,
max_outstanding,
apply_batch,
log_items_per_blob,
mmr_items_per_blob,
log_write_buffer,
mmr_write_buffer,
pool_page_size,
pool_capacity,
} = input;
let page_size = NonZeroUsize::new(usize::from(pool_page_size % 4095) + 1).unwrap();
let capacity = NonZeroUsize::new(usize::from(pool_capacity % 255) + 1).unwrap();
let log_items_per_blob =
NonZeroU64::new(u64::from(log_items_per_blob % 255) + 1).unwrap();
let mmr_items_per_blob =
NonZeroU64::new(u64::from(mmr_items_per_blob % 255) + 1).unwrap();
let log_write_buffer =
NonZeroUsize::new(usize::from(log_write_buffer % 4095) + 1).unwrap();
let mmr_write_buffer =
NonZeroUsize::new(usize::from(mmr_write_buffer % 4095) + 1).unwrap();
let base = format!("generated_6_sync_{partition_suffix}");
let resolver_config = AnyConfig {
mmr_journal_partition: format!("{base}_resolver_mmr_journal"),
mmr_items_per_blob,
mmr_write_buffer,
mmr_metadata_partition: format!("{base}_resolver_mmr_meta"),
log_journal_partition: format!("{base}_resolver_log_journal"),
log_items_per_blob,
log_write_buffer,
translator: TwoCap,
thread_pool: None,
buffer_pool: PoolRef::new(page_size, capacity),
};
let local_config = AnyConfig {
mmr_journal_partition: format!("{base}_local_mmr_journal"),
mmr_items_per_blob,
mmr_write_buffer,
mmr_metadata_partition: format!("{base}_local_mmr_meta"),
log_journal_partition: format!("{base}_local_log_journal"),
log_items_per_blob,
log_write_buffer,
translator: TwoCap,
thread_pool: None,
buffer_pool: PoolRef::new(page_size, capacity),
};
let target_db = match TestDb::init(context.clone(), resolver_config.clone()).await {
Ok(db) => db,
Err(_) => return,
};
let mut hasher = StandardHasher::<Sha256>::new();
let target_root = target_db.root(&mut hasher);
let resolver = Arc::new(RwLock::new(target_db));
let offset = u64::from(start_offset) + 1;
let start_value = MAX_LOCATION.saturating_sub(offset);
if start_value >= MAX_LOCATION {
return;
}
let Some(start_loc) = Location::new(start_value) else {
return;
};
let Some(end_loc) = Location::new(MAX_LOCATION) else {
return;
};
if start_loc >= end_loc {
return;
}
let extra = u64::from(extra_batch);
let overflow_span = MAX_LOCATION.saturating_sub(start_value).saturating_add(1);
let Some(fetch_batch_size) = NonZeroU64::new(overflow_span.saturating_add(extra))
else {
return;
};
let max_outstanding_requests = usize::from(max_outstanding) + 2;
let apply_batch_size = usize::from(apply_batch).max(1);
let engine_config: EngineConfig<TestDb, Arc<RwLock<TestDb>>> = EngineConfig {
context: context.clone(),
resolver,
target: Target {
root: target_root,
range: start_loc..end_loc,
},
max_outstanding_requests,
fetch_batch_size,
apply_batch_size,
db_config: local_config,
update_rx: None,
};
let _ = sync::sync(engine_config).await;
}
});
});
thread panicked at storage/src/adb/sync/gaps.rs:51
called
Option::unwrap()on aNonevalue