Skip to content

panicking at storage/src/adb/sync/gaps.rs:51 #2068

@dnkolegov-ar

Description

@dnkolegov-ar

thread panicked at storage/src/adb/sync/gaps.rs:51
called Option::unwrap() on a None value

#![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;
        }
    });
});

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    Status

    Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions