Skip to content

Commit

Permalink
Better update expectations in fuzzer
Browse files Browse the repository at this point in the history
  • Loading branch information
diondokter committed Dec 29, 2023
1 parent 8ec2768 commit 1a781e5
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 33 deletions.
4 changes: 2 additions & 2 deletions fuzz/fuzz_targets/map_with_shutoff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ fn fuzz(ops: Input) {
}
Err(MapError::FullStorage) => {}
Err(MapError::Storage {
value: MockFlashError::EarlyShutoff,
value: MockFlashError::EarlyShutoff(_),
backtrace: _backtrace,
}) => {
match sequential_storage::map::fetch_item::<TestItem, _>(
Expand Down Expand Up @@ -189,7 +189,7 @@ fn fuzz(ops: Input) {
assert_eq!(None, map.get(&key));
}
Err(MapError::Storage {
value: MockFlashError::EarlyShutoff,
value: MockFlashError::EarlyShutoff(_),
backtrace: _backtrace,
}) => {
#[cfg(fuzzing_repro)]
Expand Down
51 changes: 25 additions & 26 deletions fuzz/fuzz_targets/queue_with_shutoff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ fn fuzz(ops: Input) {
eprintln!("{}", flash.print_items());
#[cfg(fuzzing_repro)]
eprintln!("=== OP: {op:?} ===");

match &mut op {
Op::Push(op) => {
let val: Vec<u8> = (0..op.value_len as usize % 16).map(|_| rng.gen()).collect();
Expand Down Expand Up @@ -88,30 +88,17 @@ fn fuzz(ops: Input) {
}
}
Err(Error::Storage {
value: MockFlashError::EarlyShutoff,
value: MockFlashError::EarlyShutoff(address),
backtrace: _backtrace,
}) => {
let mut peeker =
sequential_storage::queue::peek_many(&mut flash, FLASH_RANGE)
.unwrap();

let mut last_item = None;
let mut count = 0;

while let Ok(Some(data)) = peeker.next(&mut buf) {
last_item = Some(data.to_vec());
count += 1;
}

if let Some(last_item) = last_item {
if order.get(count).is_none() && last_item == val {
#[cfg(fuzzing_repro)]
eprintln!("Early shutoff when pushing {val:?}! (but it still stored fully). Originated from:\n{_backtrace:#}");
order.push_back(val);
} else {
#[cfg(fuzzing_repro)]
eprintln!("Early shutoff when pushing {val:?}! Originated from:\n{_backtrace:#}");
}
// We need to check if it managed to write
if let Some(true) = flash.get_item_presence(address) {
#[cfg(fuzzing_repro)]
eprintln!("Early shutoff when pushing {val:?}! (but it still stored fully). Originated from:\n{_backtrace:#}");
order.push_back(val);
} else {
#[cfg(fuzzing_repro)]
eprintln!("Early shutoff when pushing {val:?}! Originated from:\n{_backtrace:#}");
}
}
Err(Error::Corrupted {
Expand Down Expand Up @@ -141,15 +128,18 @@ fn fuzz(ops: Input) {
);
}
Err(Error::Storage {
value: MockFlashError::EarlyShutoff,
value: MockFlashError::EarlyShutoff(address),
backtrace: _backtrace,
}) => {
#[cfg(fuzzing_repro)]
eprintln!(
"Early shutoff when popping (single)! Originated from:\n{_backtrace:#}"
);

retry = true;
if !matches!(flash.get_item_presence(address), Some(true)) {
// The item is no longer readable here
order.pop_front();
}
}
Err(Error::Corrupted {
backtrace: _backtrace,
Expand Down Expand Up @@ -182,13 +172,22 @@ fn fuzz(ops: Input) {
);
}
Err(Error::Storage {
value: MockFlashError::EarlyShutoff,
value: MockFlashError::EarlyShutoff(address),
backtrace: _backtrace,
}) => {
#[cfg(fuzzing_repro)]
eprintln!(
"Early shutoff when popping (many)! Originated from:\n{_backtrace:#}"
);

if !matches!(flash.get_item_presence(address), Some(true)) {
// The item is no longer readable here
order.pop_front();
}

retry = true;
*n -= i;
break;
}
Err(Error::Corrupted {
backtrace: _backtrace,
Expand Down
66 changes: 61 additions & 5 deletions src/mock_flash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,16 +86,16 @@ impl<const PAGES: usize, const BYTES_PER_WORD: usize, const PAGE_WORDS: usize>
}
}

fn check_shutoff(&mut self, _address: u32, _operation: &str) -> Result<(), MockFlashError> {
fn check_shutoff(&mut self, address: u32, _operation: &str) -> Result<(), MockFlashError> {
if let Some(bytes_until_shutoff) = self.bytes_until_shutoff.as_mut() {
if let Some(next) = bytes_until_shutoff.checked_sub(1) {
*bytes_until_shutoff = next;
Ok(())
} else {
#[cfg(fuzzing_repro)]
eprintln!("!!! Shutoff at {_address} while doing '{_operation}' !!!");
eprintln!("!!! Shutoff at {address} while doing '{_operation}' !!!");
self.bytes_until_shutoff = None;
Err(MockFlashError::EarlyShutoff)
Err(MockFlashError::EarlyShutoff(address))
}
} else {
Ok(())
Expand Down Expand Up @@ -154,6 +154,62 @@ impl<const PAGES: usize, const BYTES_PER_WORD: usize, const PAGE_WORDS: usize>

s
}

#[cfg(feature = "_test")]
/// Get the presence of the item at the given address.
///
/// - If some, the item is there.
/// - If true, the item is present and fine.
/// - If false, the item is corrupt or erased.
pub fn get_item_presence(&mut self, target_item_address: u32) -> Option<bool> {
use crate::NorFlashExt;

if !Self::FULL_FLASH_RANGE.contains(&target_item_address) {
return None;
}

let mut buf = [0; 1024 * 16];

let page_index =
crate::calculate_page_index::<Self>(Self::FULL_FLASH_RANGE, target_item_address);

let page_data_start =
crate::calculate_page_address::<Self>(Self::FULL_FLASH_RANGE, page_index)
+ Self::WORD_SIZE as u32;
let page_data_end =
crate::calculate_page_end_address::<Self>(Self::FULL_FLASH_RANGE, page_index)
- Self::WORD_SIZE as u32;

let found_item = crate::item::read_item_headers(
self,
page_data_start,
page_data_end,
|flash, header, item_address| {
let next_item_address = header.next_item_address::<Self>(item_address);

if (item_address..next_item_address).contains(&target_item_address) {
let maybe_item = header
.read_item(flash, &mut buf, item_address, page_data_end)
.unwrap();

match maybe_item {
crate::item::MaybeItem::Corrupted(_, _)
| crate::item::MaybeItem::Erased(_) => {
core::ops::ControlFlow::Break(Some(false))
}
crate::item::MaybeItem::Present(_) => {
core::ops::ControlFlow::Break(Some(true))
}
}
} else {
core::ops::ControlFlow::Continue(())
}
},
)
.unwrap();

found_item.flatten()
}
}

impl<const PAGES: usize, const BYTES_PER_WORD: usize, const PAGE_WORDS: usize> ErrorType
Expand Down Expand Up @@ -269,7 +325,7 @@ pub enum MockFlashError {
/// Location not writeable.
NotWritable(u32),
/// We got a shutoff
EarlyShutoff,
EarlyShutoff(u32),
}

impl NorFlashError for MockFlashError {
Expand All @@ -278,7 +334,7 @@ impl NorFlashError for MockFlashError {
MockFlashError::OutOfBounds => NorFlashErrorKind::OutOfBounds,
MockFlashError::NotAligned => NorFlashErrorKind::NotAligned,
MockFlashError::NotWritable(_) => NorFlashErrorKind::Other,
MockFlashError::EarlyShutoff => NorFlashErrorKind::Other,
MockFlashError::EarlyShutoff(_) => NorFlashErrorKind::Other,
}
}
}

0 comments on commit 1a781e5

Please sign in to comment.