aboutsummaryrefslogtreecommitdiff
path: root/src/zip
diff options
context:
space:
mode:
Diffstat (limited to 'src/zip')
-rw-r--r--src/zip/driver.rs70
-rw-r--r--src/zip/error.rs8
2 files changed, 41 insertions, 37 deletions
diff --git a/src/zip/driver.rs b/src/zip/driver.rs
index 7758479..0502c85 100644
--- a/src/zip/driver.rs
+++ b/src/zip/driver.rs
@@ -79,7 +79,7 @@ impl<Io: Read + Seek> ArchiveRead for Zip<Io> {
79 // Search eocdr 79 // Search eocdr
80 let limit = 65557.min(io.seek(SeekFrom::End(0))?) as i64; 80 let limit = 65557.min(io.seek(SeekFrom::End(0))?) as i64;
81 let start = io.seek(SeekFrom::End(-limit))?; 81 let start = io.seek(SeekFrom::End(-limit))?;
82 let pos = start 82 let eocdr_pos = start
83 + io.read_vec( 83 + io.read_vec(
84 (limit as usize) 84 (limit as usize)
85 .checked_sub(18) 85 .checked_sub(18)
@@ -90,46 +90,50 @@ impl<Io: Read + Seek> ArchiveRead for Zip<Io> {
90 .ok_or(ZipError::StructNotFound("Eocdr"))? as u64; 90 .ok_or(ZipError::StructNotFound("Eocdr"))? as u64;
91 91
92 // Read eocdr 92 // Read eocdr
93 io.seek(SeekFrom::Start(pos + 4))?; 93 io.seek(SeekFrom::Start(eocdr_pos + 4))?;
94 let buf = io.read_arr::<18>()?; 94 let buf = io.read_arr::<18>()?;
95 let eocdr: Eocdr = deserialize(&buf).unwrap(); 95 let eocdr: Eocdr = deserialize(&buf).unwrap();
96 let comment = String::from_cp437(io.read_vec(eocdr.comment_len as usize)?); 96 let comment = String::from_cp437(io.read_vec(eocdr.comment_len as usize)?);
97 97
98 let mut cd_pointer = eocdr.cd_pointer as u64;
99 let mut cd_size = eocdr.cd_size as u64;
100 let mut cd_records = eocdr.cd_records as u64;
101
98 // Try to find eocdr64locator 102 // Try to find eocdr64locator
99 io.seek(SeekFrom::Start(pos.saturating_sub(20)))?; 103 if eocdr_pos >= 20 {
100 let buf = io.read_arr::<20>()?; 104 io.seek(SeekFrom::Start(eocdr_pos - 20))?;
101 let (cd_pointer, cd_size, cd_records) = if buf[..4] == EOCDR64_LOCATOR_SIGNATURE { 105 let buf = io.read_arr::<20>()?;
102 // Locator found
103 let eocdr64locator: Eocdr64Locator = deserialize(&buf[4..]).unwrap();
104
105 io.seek(SeekFrom::Start(eocdr64locator.eocdr64_pointer))?;
106 if io.read_arr()? != EOCDR64_SIGNATURE {
107 return Err(ZipError::InvalidSignature("Eocdr64"));
108 }
109 106
110 let eocdr64: Eocdr64 = deserialize(&io.read_arr::<52>()?).unwrap(); 107 if buf[..4] == EOCDR64_LOCATOR_SIGNATURE {
111 if eocdr64.cd_pointer + eocdr64.cd_size > eocdr64locator.eocdr64_pointer { 108 let locator: Eocdr64Locator = deserialize(&buf[4..]).unwrap();
112 return Err(ZipError::Overlapping( 109 io.seek(SeekFrom::Start(locator.eocdr64_pointer))?;
113 "Central directory records",
114 "Zip64 end of central directory record",
115 ));
116 }
117 110
118 (eocdr64.cd_pointer, eocdr64.cd_size, eocdr64.cd_records) 111 if io.read_arr()? != EOCDR64_SIGNATURE {
119 } else { 112 return Err(ZipError::InvalidSignature("Eocdr64"));
120 if (eocdr.cd_pointer + eocdr.cd_size) as u64 > pos { 113 }
121 return Err(ZipError::Overlapping( 114
122 "Central directory records", 115 if locator.eocdr64_pointer + 76 > eocdr_pos {
123 "End of central directory record", 116 return Err(ZipError::Overlapping("Eocdr64", "Eocdr64Locator"));
124 )); 117 }
125 }
126 118
127 ( 119 let eocdr64: Eocdr64 = deserialize(&io.read_arr::<54>()?).unwrap();
128 eocdr.cd_pointer as u64, 120 if locator.eocdr64_pointer + eocdr64.eocdr64_size + 32 > eocdr_pos {
129 eocdr.cd_size as u64, 121 return Err(ZipError::Overlapping("Eocdr64", "Eocdr64Locator"));
130 eocdr.cd_records as u64, 122 }
131 ) 123
132 }; 124 cd_pointer = eocdr64.cd_pointer;
125 cd_size = eocdr64.cd_size;
126 cd_records = eocdr64.cd_records;
127
128 if cd_pointer + cd_size > locator.eocdr64_pointer {
129 return Err(ZipError::Overlapping("Cdr", "Eocdr64"));
130 }
131 } else if cd_pointer + cd_size > eocdr_pos {
132 return Err(ZipError::Overlapping("Cdr", "Eocdr"));
133 }
134 } else if cd_pointer + cd_size > eocdr_pos {
135 return Err(ZipError::Overlapping("Cdr", "Eocdr"));
136 }
133 137
134 // Read cd records 138 // Read cd records
135 let mut indexes = Map::with_capacity(cd_records as usize); 139 let mut indexes = Map::with_capacity(cd_records as usize);
diff --git a/src/zip/error.rs b/src/zip/error.rs
index fbc2ba1..40d45fe 100644
--- a/src/zip/error.rs
+++ b/src/zip/error.rs
@@ -31,10 +31,10 @@ impl From<IoError> for ZipError {
31impl PartialEq for ZipError { 31impl PartialEq for ZipError {
32 fn eq(&self, other: &Self) -> bool { 32 fn eq(&self, other: &Self) -> bool {
33 match (self, other) { 33 match (self, other) {
34 (Self::Io(l0), Self::Io(r0)) => l0.kind() == r0.kind(), 34 (Self::Io(l), Self::Io(r)) => l.kind() == r.kind(),
35 (Self::StructNotFound(l0), Self::StructNotFound(r0)) => l0 == r0, 35 (Self::StructNotFound(l), Self::StructNotFound(r)) => l == r,
36 (Self::InvalidSignature(l0), Self::InvalidSignature(r0)) => l0 == r0, 36 (Self::InvalidSignature(l), Self::InvalidSignature(r)) => l == r,
37 (Self::InvalidField(l0), Self::InvalidField(r0)) => l0 == r0, 37 (Self::InvalidField(l), Self::InvalidField(r)) => l == r,
38 (Self::Overlapping(l0, l1), Self::Overlapping(r0, r1)) => l0 == r0 && l1 == r1, 38 (Self::Overlapping(l0, l1), Self::Overlapping(r0, r1)) => l0 == r0 && l1 == r1,
39 _ => core::mem::discriminant(self) == core::mem::discriminant(other), 39 _ => core::mem::discriminant(self) == core::mem::discriminant(other),
40 } 40 }