From b098321fc24469067f3c8e202c0eadb524bfea16 Mon Sep 17 00:00:00 2001 From: Ivan Krivosheev Date: Mon, 11 Sep 2023 21:11:04 +0300 Subject: [PATCH 1/3] fix: Truncated fat entries on error --- src/internal/alloc.rs | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/src/internal/alloc.rs b/src/internal/alloc.rs index e4800e2..3bf122f 100644 --- a/src/internal/alloc.rs +++ b/src/internal/alloc.rs @@ -83,12 +83,17 @@ impl Allocator { } fn validate(&mut self, validation: Validation) -> io::Result<()> { - if self.fat.len() > self.sectors.num_sectors() as usize { - malformed!( - "FAT has {} entries, but file has only {} sectors", - self.fat.len(), - self.sectors.num_sectors() - ); + let num_sectors = self.sectors.num_sectors() as usize; + if self.fat.len() > num_sectors { + if validation.is_strict() { + malformed!( + "FAT has {} entries, but file has only {} sectors", + self.fat.len(), + num_sectors + ); + } else { + self.fat.truncate(num_sectors) + } } for &difat_sector in self.difat_sector_ids.iter() { let difat_sector_index = difat_sector as usize; @@ -134,12 +139,17 @@ impl Allocator { 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() { - malformed!( - "FAT has {} entries, but sector {} points to {}", - self.fat.len(), - from_sector, - to_sector - ); + if validation.is_strict() { + malformed!( + "FAT has {} entries, but sector {} points to {}", + self.fat.len(), + from_sector, + to_sector + ); + } else { + self.fat.truncate(from_sector + 1); + return Ok(()); + } } if pointees.contains(&to_sector) { malformed!("sector {} pointed to twice", to_sector); From fa618695e9f22ef19715e6311ef1e2d5467c5ebe Mon Sep 17 00:00:00 2001 From: Radmir Date: Fri, 23 Aug 2024 11:44:26 +0300 Subject: [PATCH 2/3] read incomplete data in permissive mode --- src/internal/alloc.rs | 39 ++++++++++++++++----------------------- src/internal/stream.rs | 29 ++++++++++++++++++++++++++--- 2 files changed, 42 insertions(+), 26 deletions(-) diff --git a/src/internal/alloc.rs b/src/internal/alloc.rs index 3bf122f..c7d84a6 100644 --- a/src/internal/alloc.rs +++ b/src/internal/alloc.rs @@ -84,16 +84,12 @@ impl Allocator { fn validate(&mut self, validation: Validation) -> io::Result<()> { let num_sectors = self.sectors.num_sectors() as usize; - if self.fat.len() > num_sectors { - if validation.is_strict() { - malformed!( - "FAT has {} entries, but file has only {} sectors", - self.fat.len(), - num_sectors - ); - } else { - self.fat.truncate(num_sectors) - } + if self.fat.len() > num_sectors && validation.is_strict() { + malformed!( + "FAT has {} entries, but file has only {} sectors", + self.fat.len(), + num_sectors + ); } for &difat_sector in self.difat_sector_ids.iter() { let difat_sector_index = difat_sector as usize; @@ -138,18 +134,15 @@ 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 validation.is_strict() { - malformed!( - "FAT has {} entries, but sector {} points to {}", - self.fat.len(), - from_sector, - to_sector - ); - } else { - self.fat.truncate(from_sector + 1); - return Ok(()); - } + if to_sector as usize >= self.fat.len() + && validation.is_strict() + { + malformed!( + "FAT has {} entries, but sector {} points to {}", + self.fat.len(), + from_sector, + to_sector + ); } if pointees.contains(&to_sector) { malformed!("sector {} pointed to twice", to_sector); @@ -514,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 bf2bdde..4770bcc 100644 --- a/src/internal/stream.rs +++ b/src/internal/stream.rs @@ -1,6 +1,6 @@ use crate::internal::{consts, MiniAllocator, ObjType, SectorInit}; use std::cell::RefCell; -use std::io::{self, BufRead, Read, Seek, SeekFrom, Write}; +use std::io::{self, BufRead, ErrorKind, Read, Seek, SeekFrom, Write}; use std::rc::{Rc, Weak}; //===========================================================================// @@ -272,6 +272,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, @@ -297,12 +318,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) From 3d22730aa937e43274c206e20f8089d921091170 Mon Sep 17 00:00:00 2001 From: Ivan Krivosheev Date: Fri, 23 Aug 2024 14:46:24 +0300 Subject: [PATCH 3/3] Fixed merge mistaces --- src/internal/stream.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/internal/stream.rs b/src/internal/stream.rs index de29915..718ce59 100644 --- a/src/internal/stream.rs +++ b/src/internal/stream.rs @@ -1,7 +1,6 @@ use crate::internal::{consts, MiniAllocator, ObjType, SectorInit}; -use std::cell::RefCell; use std::io::{self, BufRead, ErrorKind, Read, Seek, SeekFrom, Write}; -use std::rc::{Rc, Weak}; +use std::sync::{Arc, RwLock, Weak}; //===========================================================================//