Storage panic from oss-fuzz (#385)

* fixes the fuzzer flaw and adds tests for it

* out of bounds instead of empty okay
This commit is contained in:
kaczmarczyck
2021-09-24 17:46:00 +02:00
committed by GitHub
parent 930a44c105
commit 0f88d6502f
2 changed files with 76 additions and 5 deletions

View File

@@ -39,6 +39,9 @@ impl BufferUpgradeStorage {
impl UpgradeStorage for BufferUpgradeStorage {
fn read_partition(&self, offset: usize, length: usize) -> StorageResult<&[u8]> {
if length == 0 {
return Err(StorageError::OutOfBounds);
}
let partition_range = ModRange::new(0, self.partition.len());
if partition_range.contains_range(&ModRange::new(offset, length)) {
Ok(&self.partition[offset..][..length])
@@ -48,6 +51,9 @@ impl UpgradeStorage for BufferUpgradeStorage {
}
fn write_partition(&mut self, offset: usize, data: &[u8]) -> StorageResult<()> {
if data.is_empty() {
return Err(StorageError::OutOfBounds);
}
let partition_range = ModRange::new(0, self.partition.len());
if partition_range.contains_range(&ModRange::new(offset, data.len())) {
self.partition[offset..][..data.len()].copy_from_slice(data);
@@ -79,3 +85,64 @@ impl UpgradeStorage for BufferUpgradeStorage {
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn read_write_partition() {
let mut storage = BufferUpgradeStorage::new().unwrap();
assert_eq!(storage.read_partition(0, 2).unwrap(), &[0xFF, 0xFF]);
assert!(storage.write_partition(1, &[0x88, 0x88]).is_ok());
assert_eq!(storage.read_partition(0, 2).unwrap(), &[0xFF, 0x88]);
assert_eq!(
storage.write_partition(PARTITION_LENGTH - 1, &[0x88, 0x88]),
Err(StorageError::OutOfBounds)
);
assert_eq!(
storage.read_partition(PARTITION_LENGTH - 2, 2).unwrap(),
&[0xFF, 0xFF]
);
assert_eq!(
storage.read_partition(PARTITION_LENGTH - 1, 2),
Err(StorageError::OutOfBounds)
);
assert_eq!(
storage.write_partition(4, &[]),
Err(StorageError::OutOfBounds)
);
assert_eq!(
storage.write_partition(PARTITION_LENGTH + 4, &[]),
Err(StorageError::OutOfBounds)
);
assert_eq!(storage.read_partition(4, 0), Err(StorageError::OutOfBounds));
assert_eq!(
storage.read_partition(PARTITION_LENGTH + 4, 0),
Err(StorageError::OutOfBounds)
);
}
#[test]
fn partition_slice() {
let storage = BufferUpgradeStorage::new().unwrap();
assert_eq!(storage.partition_address(), 0x60000);
assert_eq!(storage.partition_length(), PARTITION_LENGTH);
}
#[test]
fn read_write_metadata() {
let mut storage = BufferUpgradeStorage::new().unwrap();
assert_eq!(storage.read_metadata().unwrap(), &[0xFF; METADATA_LENGTH]);
assert!(storage.write_metadata(&[0x88, 0x88]).is_ok());
assert_eq!(
storage.write_metadata(&[0x88; METADATA_LENGTH + 1]),
Err(StorageError::OutOfBounds)
);
let new_metadata = storage.read_metadata().unwrap();
assert_eq!(&new_metadata[0..2], &[0x88, 0x88]);
assert_eq!(&new_metadata[2..], &[0xFF; METADATA_LENGTH - 2]);
assert!(storage.write_metadata(&[]).is_ok());
assert_eq!(storage.read_metadata().unwrap(), &[0xFF; METADATA_LENGTH]);
}
}

View File

@@ -289,6 +289,9 @@ impl SyscallUpgradeStorage {
impl UpgradeStorage for SyscallUpgradeStorage {
fn read_partition(&self, offset: usize, length: usize) -> StorageResult<&[u8]> {
if length == 0 {
return Err(StorageError::OutOfBounds);
}
let address = self.partition.start() + offset;
if self
.partition
@@ -301,14 +304,15 @@ impl UpgradeStorage for SyscallUpgradeStorage {
}
fn write_partition(&mut self, offset: usize, data: &[u8]) -> StorageResult<()> {
if data.is_empty() {
return Err(StorageError::OutOfBounds);
}
let address = self.partition.start() + offset;
if self
.partition
.contains_range(&ModRange::new(address, data.len()))
{
let write_range = ModRange::new(address, data.len());
if self.partition.contains_range(&write_range) {
// Erases all pages that have their first byte in the write range.
// Since we expect calls in order, we don't want to erase half-written pages.
for address in ModRange::new(address, data.len()).aligned_iter(self.page_size) {
for address in write_range.aligned_iter(self.page_size) {
erase_page(address, self.page_size)?;
}
write_slice(address, data)