Do not crash with dirty init

This commit is contained in:
Julien Cretin
2020-11-30 10:29:18 +01:00
parent 44b35169af
commit f548a35f01
3 changed files with 24 additions and 13 deletions

View File

@@ -133,7 +133,7 @@ impl<'a> Fuzzer<'a> {
page_size: 1 << self.entropy.read_range(5, 12), page_size: 1 << self.entropy.read_range(5, 12),
max_word_writes: 2, max_word_writes: 2,
max_page_erases: self.entropy.read_range(0, 50000), max_page_erases: self.entropy.read_range(0, 50000),
strict_write: true, strict_mode: true,
}; };
let num_pages = self.entropy.read_range(3, 64); let num_pages = self.entropy.read_range(3, 64);
self.record(StatKey::PageSize, options.page_size); self.record(StatKey::PageSize, options.page_size);
@@ -156,7 +156,7 @@ impl<'a> Fuzzer<'a> {
if self.debug { if self.debug {
println!("Start with dirty storage."); println!("Start with dirty storage.");
} }
options.strict_write = false; options.strict_mode = false;
let storage = BufferStorage::new(storage, options); let storage = BufferStorage::new(storage, options);
StoreDriver::Off(StoreDriverOff::new_dirty(storage)) StoreDriver::Off(StoreDriverOff::new_dirty(storage))
} else if self.entropy.read_bit() { } else if self.entropy.read_bit() {

View File

@@ -23,9 +23,9 @@ use alloc::vec;
/// for tests and fuzzing, for which it has dedicated functionalities. /// for tests and fuzzing, for which it has dedicated functionalities.
/// ///
/// This storage tracks how many times words are written between page erase cycles, how many times /// This storage tracks how many times words are written between page erase cycles, how many times
/// pages are erased, and whether an operation flips bits in the wrong direction (optional). /// pages are erased, and whether an operation flips bits in the wrong direction. Operations panic
/// Operations panic if those conditions are broken. This storage also permits to interrupt /// if those conditions are broken (optional). This storage also permits to interrupt operations for
/// operations for inspection or to corrupt the operation. /// inspection or to corrupt the operation.
#[derive(Clone)] #[derive(Clone)]
pub struct BufferStorage { pub struct BufferStorage {
/// Content of the storage. /// Content of the storage.
@@ -59,8 +59,13 @@ pub struct BufferOptions {
/// How many times a page can be erased. /// How many times a page can be erased.
pub max_page_erases: usize, pub max_page_erases: usize,
/// Whether bits cannot be written from 0 to 1. /// Whether the storage should check the flash invariant.
pub strict_write: bool, ///
/// When set, the following conditions would panic:
/// - A bit is written from 0 to 1.
/// - A word is written more than `max_word_writes`.
/// - A page is erased more than `max_page_erases`.
pub strict_mode: bool,
} }
/// Corrupts a slice given actual and expected value. /// Corrupts a slice given actual and expected value.
@@ -214,7 +219,10 @@ impl BufferStorage {
/// ///
/// Panics if the maximum number of erase cycles per page is reached. /// Panics if the maximum number of erase cycles per page is reached.
fn incr_page_erases(&mut self, page: usize) { fn incr_page_erases(&mut self, page: usize) {
// Check that pages are not erased too many times.
if self.options.strict_mode {
assert!(self.page_erases[page] < self.max_page_erases()); assert!(self.page_erases[page] < self.max_page_erases());
}
self.page_erases[page] += 1; self.page_erases[page] += 1;
let num_words = self.page_size() / self.word_size(); let num_words = self.page_size() / self.word_size();
for word in 0..num_words { for word in 0..num_words {
@@ -252,7 +260,10 @@ impl BufferStorage {
continue; continue;
} }
let word = index / word_size + i; let word = index / word_size + i;
// Check that words are not written too many times.
if self.options.strict_mode {
assert!(self.word_writes[word] < self.max_word_writes()); assert!(self.word_writes[word] < self.max_word_writes());
}
self.word_writes[word] += 1; self.word_writes[word] += 1;
} }
} }
@@ -306,8 +317,8 @@ impl Storage for BufferStorage {
self.interruption.tick(&operation)?; self.interruption.tick(&operation)?;
// Check and update counters. // Check and update counters.
self.incr_word_writes(range.start, value, value); self.incr_word_writes(range.start, value, value);
// Check strict write. // Check that bits are correctly flipped.
if self.options.strict_write { if self.options.strict_mode {
for (byte, &val) in range.clone().zip(value.iter()) { for (byte, &val) in range.clone().zip(value.iter()) {
assert_eq!(self.storage[byte] & val, val); assert_eq!(self.storage[byte] & val, val);
} }
@@ -472,7 +483,7 @@ mod tests {
page_size: 16, page_size: 16,
max_word_writes: 2, max_word_writes: 2,
max_page_erases: 3, max_page_erases: 3,
strict_write: true, strict_mode: true,
}; };
// Those words are decreasing bit patterns. Bits are only changed from 1 to 0 and at least one // Those words are decreasing bit patterns. Bits are only changed from 1 to 0 and at least one
// bit is changed. // bit is changed.

View File

@@ -1257,7 +1257,7 @@ mod tests {
page_size: self.page_size, page_size: self.page_size,
max_word_writes: self.max_word_writes, max_word_writes: self.max_word_writes,
max_page_erases: self.max_page_erases, max_page_erases: self.max_page_erases,
strict_write: true, strict_mode: true,
}; };
StoreDriverOff::new(options, self.num_pages) StoreDriverOff::new(options, self.num_pages)
} }