diff options
| author | igorechek06 <me@igorek.dev> | 2024-08-10 17:18:03 +0900 |
|---|---|---|
| committer | igorechek06 <me@igorek.dev> | 2024-08-10 17:18:43 +0900 |
| commit | 866516ac50851e2827e6aff0a98c444268c566ff (patch) | |
| tree | 1134bf6f714d75a1050befa0f67bddd2d4b085c8 /src/zip/driver.rs | |
| parent | 51f2737ca7af016e3dd3ad03673f48a754a1642e (diff) | |
| download | archivator-866516ac50851e2827e6aff0a98c444268c566ff.tar.gz archivator-866516ac50851e2827e6aff0a98c444268c566ff.zip | |
Add overlap checking
Diffstat (limited to 'src/zip/driver.rs')
| -rw-r--r-- | src/zip/driver.rs | 26 |
1 files changed, 18 insertions, 8 deletions
diff --git a/src/zip/driver.rs b/src/zip/driver.rs index b4217c8..9dccfd0 100644 --- a/src/zip/driver.rs +++ b/src/zip/driver.rs | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | use crate::driver::{ArchiveRead, ArchiveWrite, Driver}; | 1 | use crate::driver::{ArchiveRead, ArchiveWrite, Driver}; |
| 2 | use crate::utils::ReadUtils; | 2 | use crate::utils::{IoCursor, ReadUtils}; |
| 3 | use crate::zip::cp437::FromCp437; | 3 | use crate::zip::cp437::FromCp437; |
| 4 | use crate::zip::datetime::DosDateTime; | 4 | use crate::zip::datetime::DosDateTime; |
| 5 | use crate::zip::structs::{ | 5 | use crate::zip::structs::{ |
| @@ -106,12 +106,19 @@ impl<Io: Read + Seek> ArchiveRead for Zip<Io> { | |||
| 106 | io.seek(SeekFrom::Start(eocdr64locator.eocdr64_pointer))?; | 106 | io.seek(SeekFrom::Start(eocdr64locator.eocdr64_pointer))?; |
| 107 | let buf = io.read_arr::<56>()?; | 107 | let buf = io.read_arr::<56>()?; |
| 108 | if buf[0..4] != EOCDR64_SIGNATURE { | 108 | if buf[0..4] != EOCDR64_SIGNATURE { |
| 109 | return Err(ZipError::InvalidEOCDR64Signature); | 109 | return Err(ZipError::InvalidEocdr64Signature); |
| 110 | } | 110 | } |
| 111 | let eocdr64: Eocdr64 = deserialize(&buf[4..]).unwrap(); | 111 | let eocdr64: Eocdr64 = deserialize(&buf[4..]).unwrap(); |
| 112 | if eocdr64.cd_pointer + eocdr64.cd_size > eocdr64locator.eocdr64_pointer { | ||
| 113 | return Err(ZipError::Overlapping("Central directory records", "Zip64 end of central directory record")); | ||
| 114 | } | ||
| 112 | 115 | ||
| 113 | (eocdr64.cd_pointer, eocdr64.cd_size, eocdr64.cd_records) | 116 | (eocdr64.cd_pointer, eocdr64.cd_size, eocdr64.cd_records) |
| 114 | } else { | 117 | } else { |
| 118 | if (eocdr.cd_pointer + eocdr.cd_size) as u64 > pos { | ||
| 119 | return Err(ZipError::Overlapping("Central directory records", "End of central directory record")); | ||
| 120 | } | ||
| 121 | |||
| 115 | ( | 122 | ( |
| 116 | eocdr.cd_pointer as u64, | 123 | eocdr.cd_pointer as u64, |
| 117 | eocdr.cd_size as u64, | 124 | eocdr.cd_size as u64, |
| @@ -123,27 +130,30 @@ impl<Io: Read + Seek> ArchiveRead for Zip<Io> { | |||
| 123 | let mut indexes = Map::with_capacity(cd_records as usize); | 130 | let mut indexes = Map::with_capacity(cd_records as usize); |
| 124 | let mut files = Vec::with_capacity(cd_records as usize); | 131 | let mut files = Vec::with_capacity(cd_records as usize); |
| 125 | io.seek(SeekFrom::Start(cd_pointer))?; | 132 | io.seek(SeekFrom::Start(cd_pointer))?; |
| 126 | let mut buf_reader = BufReader::with_capacity(cd_size.min(131072) as usize, &mut io); | 133 | let mut cd_reader = BufReader::with_capacity( |
| 134 | cd_size.min(131072) as usize, | ||
| 135 | IoCursor::new(&mut io, cd_pointer, cd_pointer + cd_size), | ||
| 136 | ); | ||
| 127 | 137 | ||
| 128 | for i in 0..cd_records as usize { | 138 | for i in 0..cd_records as usize { |
| 129 | let buf = buf_reader.read_arr::<46>()?; | 139 | let buf = cd_reader.read_arr::<46>()?; |
| 130 | 140 | ||
| 131 | if buf[..4] != CDR_SIGNATURE { | 141 | if buf[..4] != CDR_SIGNATURE { |
| 132 | return Err(ZipError::InvalidCDRSignature); | 142 | return Err(ZipError::InvalidCdrSignature); |
| 133 | } | 143 | } |
| 134 | let cdr: Cdr = deserialize(&buf[4..46]).unwrap(); | 144 | let cdr: Cdr = deserialize(&buf[4..46]).unwrap(); |
| 135 | let bit_flag = BitFlag::new(cdr.bit_flag); | 145 | let bit_flag = BitFlag::new(cdr.bit_flag); |
| 136 | 146 | ||
| 137 | let name = buf_reader.read_vec(cdr.name_len as usize)?; | 147 | let name = cd_reader.read_vec(cdr.name_len as usize)?; |
| 138 | let name = if bit_flag.is_utf8() { | 148 | let name = if bit_flag.is_utf8() { |
| 139 | String::from_utf8(name).map_err(|_| ZipError::InvalidFileName)? | 149 | String::from_utf8(name).map_err(|_| ZipError::InvalidFileName)? |
| 140 | } else { | 150 | } else { |
| 141 | String::from_cp437(name) | 151 | String::from_cp437(name) |
| 142 | }; | 152 | }; |
| 143 | 153 | ||
| 144 | let extra_fields = buf_reader.read_vec(cdr.extra_field_len as usize)?; | 154 | let extra_fields = cd_reader.read_vec(cdr.extra_field_len as usize)?; |
| 145 | 155 | ||
| 146 | let comment = buf_reader.read_vec(cdr.comment_len as usize)?; | 156 | let comment = cd_reader.read_vec(cdr.comment_len as usize)?; |
| 147 | let comment = if bit_flag.is_utf8() { | 157 | let comment = if bit_flag.is_utf8() { |
| 148 | String::from_utf8(comment).map_err(|_| ZipError::InvalidFileComment)? | 158 | String::from_utf8(comment).map_err(|_| ZipError::InvalidFileComment)? |
| 149 | } else { | 159 | } else { |
