Skip to content

Commit 3e6bd0a

Browse files
authored
Merge pull request #66 from sftse/pad-with-free
Pad with free
2 parents af86856 + 556d272 commit 3e6bd0a

File tree

4 files changed

+134
-24
lines changed

4 files changed

+134
-24
lines changed

src/internal/alloc.rs

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -92,43 +92,37 @@ impl<F> Allocator<F> {
9292
}
9393
for &difat_sector in self.difat_sector_ids.iter() {
9494
let difat_sector_index = difat_sector as usize;
95-
if difat_sector_index >= self.fat.len() {
95+
let Some(sector) = self.fat.get_mut(difat_sector_index) else {
9696
malformed!(
9797
"FAT has {} entries, but DIFAT lists {} as a DIFAT sector",
9898
self.fat.len(),
9999
difat_sector
100100
);
101+
};
102+
if *sector != consts::DIFAT_SECTOR && validation.is_strict() {
103+
malformed!(
104+
"DIFAT sector {} is not marked as such in the FAT",
105+
difat_sector
106+
);
101107
}
102-
if self.fat[difat_sector_index] != consts::DIFAT_SECTOR {
103-
if validation.is_strict() {
104-
malformed!(
105-
"DIFAT sector {} is not marked as such in the FAT",
106-
difat_sector
107-
);
108-
} else {
109-
self.fat[difat_sector_index] = consts::DIFAT_SECTOR;
110-
}
111-
}
108+
*sector = consts::DIFAT_SECTOR;
112109
}
113110
for &fat_sector in self.difat.iter() {
114111
let fat_sector_index = fat_sector as usize;
115-
if fat_sector_index >= self.fat.len() {
112+
let Some(sector) = self.fat.get_mut(fat_sector_index) else {
116113
malformed!(
117114
"FAT has {} entries, but DIFAT lists {} as a FAT sector",
118115
self.fat.len(),
119116
fat_sector
120117
);
118+
};
119+
if *sector != consts::FAT_SECTOR && validation.is_strict() {
120+
malformed!(
121+
"FAT sector {} is not marked as such in the FAT",
122+
fat_sector
123+
);
121124
}
122-
if self.fat[fat_sector_index] != consts::FAT_SECTOR {
123-
if validation.is_strict() {
124-
malformed!(
125-
"FAT sector {} is not marked as such in the FAT",
126-
fat_sector
127-
);
128-
} else {
129-
self.fat[fat_sector_index] = consts::FAT_SECTOR;
130-
}
131-
}
125+
*sector = consts::FAT_SECTOR;
132126
}
133127
let mut pointees = FnvHashSet::default();
134128
for (from_sector, &to_sector) in self.fat.iter().enumerate() {

src/internal/consts.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,75 @@ pub const ROOT_STREAM_ID: u32 = 0;
3333
pub const MAX_REGULAR_STREAM_ID: u32 = 0xfffffffa;
3434
pub const NO_STREAM: u32 = 0xffffffff;
3535

36+
pub(crate) fn prettify(sectors: &[u32]) -> Vec<Type> {
37+
let mut fmt = Vec::new();
38+
for s in sectors.iter() {
39+
match *s {
40+
END_OF_CHAIN => fmt.push(Type::End),
41+
FREE_SECTOR => fmt.push(Type::Free),
42+
DIFAT_SECTOR => fmt.push(Type::Difat),
43+
FAT_SECTOR => fmt.push(Type::Fat),
44+
i => {
45+
if let Some(Type::Range(_, end)) = fmt.last_mut() {
46+
if *end + 1 == i {
47+
*end += 1;
48+
continue;
49+
}
50+
}
51+
fmt.push(Type::Range(i, i));
52+
}
53+
};
54+
}
55+
fmt
56+
}
57+
58+
#[derive(Clone, PartialEq, Eq)]
59+
pub(crate) enum Type {
60+
Free,
61+
End,
62+
Fat,
63+
Difat,
64+
Range(u32, u32),
65+
}
66+
67+
impl std::fmt::Debug for Type {
68+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
69+
match self {
70+
Type::Range(start, end) if *start == *end => write!(f, "{start}"),
71+
Type::Range(start, end) => write!(f, "{start}-{end}"),
72+
Type::Free => f.write_str("FREE"),
73+
Type::End => f.write_str("EOC"),
74+
Type::Fat => f.write_str("FAT"),
75+
Type::Difat => f.write_str("DIFAT"),
76+
}
77+
}
78+
}
79+
80+
#[cfg(test)]
81+
mod tests {
82+
use super::*;
83+
84+
#[test]
85+
fn test_prettify_sectors() {
86+
let sectors = [
87+
END_OF_CHAIN,
88+
0,
89+
1,
90+
2,
91+
3,
92+
4,
93+
5,
94+
6,
95+
7,
96+
END_OF_CHAIN,
97+
23,
98+
25,
99+
18,
100+
FREE_SECTOR,
101+
];
102+
let s = prettify(&sectors);
103+
assert_eq!("[EOC, 0-7, EOC, 23, 25, 18, FREE]", format!("{s:?}"));
104+
}
105+
}
106+
36107
// ========================================================================= //

src/internal/header.rs

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1+
use std::fmt;
12
use std::io::{self, Read, Write};
23

34
use crate::internal::{consts, Validation, Version};
45
use crate::{ReadLeNumber, WriteLeNumber};
56

67
//===========================================================================//
78

8-
#[derive(Clone, Debug, PartialEq, Eq)]
9+
#[derive(Clone, PartialEq, Eq)]
910
pub struct Header {
1011
pub version: Version,
1112
pub num_dir_sectors: u32,
@@ -18,6 +19,47 @@ pub struct Header {
1819
pub initial_difat_entries: [u32; consts::NUM_DIFAT_ENTRIES_IN_HEADER],
1920
}
2021

22+
struct Sector(u32);
23+
24+
impl fmt::Debug for Sector {
25+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
26+
match self.0 {
27+
consts::FREE_SECTOR => f.write_str("FREE"),
28+
consts::END_OF_CHAIN => f.write_str("EOC"),
29+
consts::DIFAT_SECTOR => f.write_str("DIFAT"),
30+
consts::FAT_SECTOR => f.write_str("FAT"),
31+
i => write!(f, "{i}"),
32+
}
33+
}
34+
}
35+
36+
impl fmt::Debug for Header {
37+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38+
let start_nonfree = self
39+
.initial_difat_entries
40+
.iter()
41+
.rev()
42+
.skip_while(|elt| **elt == consts::FREE_SECTOR)
43+
.count();
44+
f.debug_struct("Header")
45+
.field("version", &self.version)
46+
.field("num_dir_sectors", &self.num_dir_sectors)
47+
.field("num_fat_sectors", &self.num_fat_sectors)
48+
.field("first_dir_sector", &Sector(self.first_dir_sector))
49+
.field("first_minifat_sector", &Sector(self.first_minifat_sector))
50+
.field("num_minifat_sectors", &self.num_minifat_sectors)
51+
.field("first_difat_sector", &Sector(self.first_difat_sector))
52+
.field("num_difat_sectors", &self.num_difat_sectors)
53+
.field(
54+
"initial_difat_entries",
55+
&consts::prettify(
56+
&self.initial_difat_entries[..start_nonfree],
57+
),
58+
)
59+
.finish()
60+
}
61+
}
62+
2163
impl Header {
2264
pub fn read_from<R: Read>(
2365
reader: &mut R,

src/lib.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -500,13 +500,16 @@ impl<F: Read + Seek> CompoundFile<F> {
500500
// case above, we can remove these even if it makes the number of FAT
501501
// entries less than the number of sectors in the file; the allocator
502502
// will implicitly treat these extra sectors as free.
503-
while fat.last() == Some(&consts::FREE_SECTOR)
503+
while fat.len() > sectors.num_sectors() as usize && fat.last() == Some(&consts::FREE_SECTOR)
504504
// strip DIFAT_SECTOR from the end
505505
|| !validation.is_strict()
506506
&& fat.len() > sectors.num_sectors() as usize && fat.last() == Some(&consts::DIFAT_SECTOR)
507507
{
508508
fat.pop();
509509
}
510+
while fat.len() < sectors.num_sectors() as usize {
511+
fat.push(consts::FREE_SECTOR);
512+
}
510513

511514
let mut allocator =
512515
Allocator::new(sectors, difat_sector_ids, difat, fat, validation)?;

0 commit comments

Comments
 (0)