diff --git a/src/internal/alloc.rs b/src/internal/alloc.rs index e4800e2..c7d84a6 100644 --- a/src/internal/alloc.rs +++ b/src/internal/alloc.rs @@ -83,11 +83,12 @@ impl Allocator { } fn validate(&mut self, validation: Validation) -> io::Result<()> { - if self.fat.len() > self.sectors.num_sectors() as usize { + let num_sectors = self.sectors.num_sectors() as usize; + if self.fat.len() > num_sectors && validation.is_strict() { malformed!( "FAT has {} entries, but file has only {} sectors", self.fat.len(), - self.sectors.num_sectors() + num_sectors ); } for &difat_sector in self.difat_sector_ids.iter() { @@ -133,7 +134,9 @@ impl Allocator { let mut pointees = FnvHashSet::default(); for (from_sector, &to_sector) in self.fat.iter().enumerate() { if to_sector <= consts::MAX_REGULAR_SECTOR { - if to_sector as usize >= self.fat.len() { + if to_sector as usize >= self.fat.len() + && validation.is_strict() + { malformed!( "FAT has {} entries, but sector {} points to {}", self.fat.len(), @@ -504,7 +507,7 @@ mod tests { fn pointee_out_of_range() { let difat = vec![0]; let fat = vec![consts::FAT_SECTOR, 2]; - make_allocator(difat, fat, Validation::Permissive); + make_allocator(difat, fat, Validation::Strict); } #[test] diff --git a/src/internal/stream.rs b/src/internal/stream.rs index 2815620..718ce59 100644 --- a/src/internal/stream.rs +++ b/src/internal/stream.rs @@ -1,5 +1,5 @@ use crate::internal::{consts, MiniAllocator, ObjType, SectorInit}; -use std::io::{self, BufRead, Read, Seek, SeekFrom, Write}; +use std::io::{self, BufRead, ErrorKind, Read, Seek, SeekFrom, Write}; use std::sync::{Arc, RwLock, Weak}; //===========================================================================// @@ -274,6 +274,27 @@ impl Flusher for FlushBuffer { //===========================================================================// +fn read_until_error( + this: &mut R, + mut buf: &mut [u8], +) -> io::Result { + let mut read_amount = 0; + + while !buf.is_empty() { + match this.read(buf) { + Ok(0) => break, + Ok(n) => { + buf = &mut buf[n..]; + read_amount += n; + } + Err(err) if err.kind() == ErrorKind::Interrupted => {} + Err(err) => return Err(err), + } + } + + Ok(read_amount) +} + fn read_data_from_stream( minialloc: &mut MiniAllocator, stream_id: u32, @@ -299,12 +320,14 @@ fn read_data_from_stream( if stream_len < consts::MINI_STREAM_CUTOFF as u64 { let mut chain = minialloc.open_mini_chain(start_sector)?; chain.seek(SeekFrom::Start(buf_offset_from_start))?; - chain.read_exact(&mut buf[..num_bytes])?; + return Ok(read_until_error(&mut chain, &mut buf[..num_bytes]) + .unwrap_or(0)); } else { let mut chain = minialloc.open_chain(start_sector, SectorInit::Zero)?; chain.seek(SeekFrom::Start(buf_offset_from_start))?; - chain.read_exact(&mut buf[..num_bytes])?; + return Ok(read_until_error(&mut chain, &mut buf[..num_bytes]) + .unwrap_or(0)); } } Ok(num_bytes)