Skip to content

Commit

Permalink
Add remove all to fuzzer
Browse files Browse the repository at this point in the history
  • Loading branch information
diondokter committed Jul 17, 2024
1 parent e1fb263 commit aea3565
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 7 deletions.
56 changes: 55 additions & 1 deletion fuzz/fuzz_targets/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ enum Op {
Store(StoreOp),
Fetch(u8),
Remove(u8),
RemoveAll,
}

#[derive(Arbitrary, Debug, Clone)]
Expand Down Expand Up @@ -64,7 +65,11 @@ enum CacheType {

fn fuzz(ops: Input, mut cache: impl KeyCacheImpl<u8> + Debug) {
let mut flash = MockFlashBase::<PAGES, WORD_SIZE, WORDS_PER_PAGE>::new(
if ops.ops.iter().any(|op| matches!(op, Op::Remove(_))) {
if ops
.ops
.iter()
.any(|op| matches!(op, Op::Remove(_) | Op::RemoveAll))
{
WriteCountCheck::Twice
} else {
WriteCountCheck::OnceOnly
Expand Down Expand Up @@ -190,6 +195,7 @@ fn fuzz(ops: Input, mut cache: impl KeyCacheImpl<u8> + Debug) {
value: MockFlashError::EarlyShutoff(_),
backtrace: _backtrace,
}) => {
// Check if the item is still there. It might or it might not and either is fine
match block_on(sequential_storage::map::fetch_item::<u8, &[u8], _>(
&mut flash,
FLASH_RANGE,
Expand Down Expand Up @@ -220,6 +226,54 @@ fn fuzz(ops: Input, mut cache: impl KeyCacheImpl<u8> + Debug) {
Err(e) => panic!("{e:?}"),
}
}
Op::RemoveAll => {
match block_on(sequential_storage::map::remove_all_items::<u8, _>(
&mut flash,
FLASH_RANGE,
&mut cache,
&mut buf.0,
)) {
Ok(()) => {
map.clear();
}
Err(Error::Storage {
value: MockFlashError::EarlyShutoff(_),
backtrace: _backtrace,
}) => {
for key in map.keys().copied().collect::<Vec<_>>() {
// Check if the item is still there. It might or it might not and either is fine
match block_on(sequential_storage::map::fetch_item::<u8, &[u8], _>(
&mut flash,
FLASH_RANGE,
&mut cache,
&mut buf.0,
key,
)) {
Ok(Some(_)) => {
#[cfg(fuzzing_repro)]
eprintln!("Early shutoff when removing item {key}! Originated from:\n{_backtrace:#}");
}
_ => {
// Could not fetch the item we stored...
#[cfg(fuzzing_repro)]
eprintln!("Early shutoff when removing item {key}! (but it still removed fully). Originated from:\n{_backtrace:#}");
// Even though we got a shutoff, it still managed to store well
map.remove(&key);
}
}
}
}

Err(Error::Corrupted {
backtrace: _backtrace,
}) => {
#[cfg(fuzzing_repro)]
eprintln!("Corrupted when removing! Originated from:\n{_backtrace:#}");
panic!("Corrupted!");
}
Err(e) => panic!("{e:?}"),
}
}
}
}
}
11 changes: 5 additions & 6 deletions src/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,7 @@ pub async fn remove_all_items<K: Key, S: MultiwriteNorFlash>(
)
}

/// If `search_key` is None, then all items will be removed
async fn remove_item_inner<K: Key, S: MultiwriteNorFlash>(
flash: &mut S,
flash_range: Range<u32>,
Expand Down Expand Up @@ -650,15 +651,13 @@ async fn remove_item_inner<K: Key, S: MultiwriteNorFlash>(
item::MaybeItem::Corrupted(_, _) => continue,
item::MaybeItem::Erased(_, _) => continue,
item::MaybeItem::Present(item) => {
let item_match = if let Some(search_key) = &search_key {
let (item_key, _) = K::deserialize_from(item.data())?;
&item_key == search_key
} else {
false
let item_match = match &search_key {
Some(search_key) => &K::deserialize_from(item.data())?.0 == search_key,
_ => true,
};
// If this item has the same key as the key we're trying to erase, then erase the item.
// But keep going! We need to erase everything.
if search_key.is_none() || item_match {
if item_match {
item.header
.erase_data(flash, flash_range.clone(), cache, item_address)
.await?;
Expand Down

0 comments on commit aea3565

Please sign in to comment.