aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorigorechek06 <me@igorek.dev>2024-08-10 17:18:03 +0900
committerigorechek06 <me@igorek.dev>2024-08-10 17:18:43 +0900
commit866516ac50851e2827e6aff0a98c444268c566ff (patch)
tree1134bf6f714d75a1050befa0f67bddd2d4b085c8
parent51f2737ca7af016e3dd3ad03673f48a754a1642e (diff)
downloadarchivator-866516ac50851e2827e6aff0a98c444268c566ff.tar.gz
archivator-866516ac50851e2827e6aff0a98c444268c566ff.zip
Add overlap checking
-rw-r--r--src/utils/cursor.rs2
-rw-r--r--src/zip/driver.rs26
-rw-r--r--src/zip/encryption/aes.rs1
-rw-r--r--src/zip/encryption/weak.rs1
-rw-r--r--src/zip/error.rs17
5 files changed, 31 insertions, 16 deletions
diff --git a/src/utils/cursor.rs b/src/utils/cursor.rs
index ee80474..cde846d 100644
--- a/src/utils/cursor.rs
+++ b/src/utils/cursor.rs
@@ -6,7 +6,7 @@ pub struct IoCursor<Io> {
6 bounds: (u64, u64), 6 bounds: (u64, u64),
7} 7}
8 8
9impl<Io: Seek> IoCursor<Io> { 9impl<Io> IoCursor<Io> {
10 pub fn new(io: Io, cursor: u64, end: u64) -> Self { 10 pub fn new(io: Io, cursor: u64, end: u64) -> Self {
11 Self { 11 Self {
12 io, 12 io,
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 @@
1use crate::driver::{ArchiveRead, ArchiveWrite, Driver}; 1use crate::driver::{ArchiveRead, ArchiveWrite, Driver};
2use crate::utils::ReadUtils; 2use crate::utils::{IoCursor, ReadUtils};
3use crate::zip::cp437::FromCp437; 3use crate::zip::cp437::FromCp437;
4use crate::zip::datetime::DosDateTime; 4use crate::zip::datetime::DosDateTime;
5use crate::zip::structs::{ 5use 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 {
diff --git a/src/zip/encryption/aes.rs b/src/zip/encryption/aes.rs
index b690482..376d01e 100644
--- a/src/zip/encryption/aes.rs
+++ b/src/zip/encryption/aes.rs
@@ -2,7 +2,6 @@ use aes::cipher::generic_array::GenericArray;
2use aes::cipher::BlockEncrypt; 2use aes::cipher::BlockEncrypt;
3use std::io::{Read, Result as IoResult}; 3use std::io::{Read, Result as IoResult};
4 4
5#[allow(dead_code)]
6pub struct AesDecoder<Io: Read, Aes: BlockEncrypt> { 5pub struct AesDecoder<Io: Read, Aes: BlockEncrypt> {
7 io: Io, 6 io: Io,
8 aes: Aes, 7 aes: Aes,
diff --git a/src/zip/encryption/weak.rs b/src/zip/encryption/weak.rs
index ebddb2d..3c35776 100644
--- a/src/zip/encryption/weak.rs
+++ b/src/zip/encryption/weak.rs
@@ -55,7 +55,6 @@ impl Keys {
55 self.key2 = crc32((self.key1 >> 24) as u8, self.key2); 55 self.key2 = crc32((self.key1 >> 24) as u8, self.key2);
56 } 56 }
57 57
58 #[allow(dead_code)]
59 pub fn encode_bytes(&mut self, byte: u8) -> u8 { 58 pub fn encode_bytes(&mut self, byte: u8) -> u8 {
60 let key = self.key2 | 2; 59 let key = self.key2 | 2;
61 self.update(byte); 60 self.update(byte);
diff --git a/src/zip/error.rs b/src/zip/error.rs
index 87cd9e9..dbb6bb5 100644
--- a/src/zip/error.rs
+++ b/src/zip/error.rs
@@ -9,9 +9,11 @@ pub enum ZipError {
9 Io(IoError), 9 Io(IoError),
10 10
11 EocdrNotFound, 11 EocdrNotFound,
12 InvalidEOCDR64Signature, 12 InvalidEocdr64Signature,
13 InvalidFileHeaderSignature, 13 InvalidFileHeaderSignature,
14 InvalidCDRSignature, 14 InvalidCdrSignature,
15
16 Overlapping(&'static str, &'static str),
15 17
16 UnsupportedCompressionMethod(u16), 18 UnsupportedCompressionMethod(u16),
17 UnsupportedEncryptionMethod, 19 UnsupportedEncryptionMethod,
@@ -53,8 +55,9 @@ impl Display for ZipError {
53 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 55 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
54 match self { 56 match self {
55 Self::Io(error) => write!(f, "{}", error), 57 Self::Io(error) => write!(f, "{}", error),
58
56 Self::EocdrNotFound => write!(f, "End of central directory record not found"), 59 Self::EocdrNotFound => write!(f, "End of central directory record not found"),
57 Self::InvalidEOCDR64Signature => { 60 Self::InvalidEocdr64Signature => {
58 write!( 61 write!(
59 f, 62 f,
60 "Invalid signature of zip64 end of central directory record" 63 "Invalid signature of zip64 end of central directory record"
@@ -63,12 +66,16 @@ impl Display for ZipError {
63 Self::InvalidFileHeaderSignature => { 66 Self::InvalidFileHeaderSignature => {
64 write!(f, "Invalid file header signature") 67 write!(f, "Invalid file header signature")
65 } 68 }
66 Self::InvalidCDRSignature => { 69 Self::InvalidCdrSignature => {
67 write!(f, "Invalid signature of central directory record") 70 write!(f, "Invalid signature of central directory record")
68 } 71 }
69 72
73 Self::Overlapping(struct1, struct2) => {
74 write!(f, "`{}` overlapt `{}`", struct1, struct2)
75 }
76
70 Self::UnsupportedCompressionMethod(id) => { 77 Self::UnsupportedCompressionMethod(id) => {
71 writeln!(f, "Unsupported compression method {}", id) 78 writeln!(f, "Unsupported compression method `{}`", id)
72 } 79 }
73 Self::UnsupportedEncryptionMethod => { 80 Self::UnsupportedEncryptionMethod => {
74 writeln!(f, "Unsupported encryption method") 81 writeln!(f, "Unsupported encryption method")