From 866516ac50851e2827e6aff0a98c444268c566ff Mon Sep 17 00:00:00 2001 From: igorechek06 Date: Sat, 10 Aug 2024 17:18:03 +0900 Subject: Add overlap checking --- src/zip/driver.rs | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) (limited to 'src/zip/driver.rs') 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 @@ use crate::driver::{ArchiveRead, ArchiveWrite, Driver}; -use crate::utils::ReadUtils; +use crate::utils::{IoCursor, ReadUtils}; use crate::zip::cp437::FromCp437; use crate::zip::datetime::DosDateTime; use crate::zip::structs::{ @@ -106,12 +106,19 @@ impl ArchiveRead for Zip { io.seek(SeekFrom::Start(eocdr64locator.eocdr64_pointer))?; let buf = io.read_arr::<56>()?; if buf[0..4] != EOCDR64_SIGNATURE { - return Err(ZipError::InvalidEOCDR64Signature); + return Err(ZipError::InvalidEocdr64Signature); } let eocdr64: Eocdr64 = deserialize(&buf[4..]).unwrap(); + if eocdr64.cd_pointer + eocdr64.cd_size > eocdr64locator.eocdr64_pointer { + return Err(ZipError::Overlapping("Central directory records", "Zip64 end of central directory record")); + } (eocdr64.cd_pointer, eocdr64.cd_size, eocdr64.cd_records) } else { + if (eocdr.cd_pointer + eocdr.cd_size) as u64 > pos { + return Err(ZipError::Overlapping("Central directory records", "End of central directory record")); + } + ( eocdr.cd_pointer as u64, eocdr.cd_size as u64, @@ -123,27 +130,30 @@ impl ArchiveRead for Zip { let mut indexes = Map::with_capacity(cd_records as usize); let mut files = Vec::with_capacity(cd_records as usize); io.seek(SeekFrom::Start(cd_pointer))?; - let mut buf_reader = BufReader::with_capacity(cd_size.min(131072) as usize, &mut io); + let mut cd_reader = BufReader::with_capacity( + cd_size.min(131072) as usize, + IoCursor::new(&mut io, cd_pointer, cd_pointer + cd_size), + ); for i in 0..cd_records as usize { - let buf = buf_reader.read_arr::<46>()?; + let buf = cd_reader.read_arr::<46>()?; if buf[..4] != CDR_SIGNATURE { - return Err(ZipError::InvalidCDRSignature); + return Err(ZipError::InvalidCdrSignature); } let cdr: Cdr = deserialize(&buf[4..46]).unwrap(); let bit_flag = BitFlag::new(cdr.bit_flag); - let name = buf_reader.read_vec(cdr.name_len as usize)?; + let name = cd_reader.read_vec(cdr.name_len as usize)?; let name = if bit_flag.is_utf8() { String::from_utf8(name).map_err(|_| ZipError::InvalidFileName)? } else { String::from_cp437(name) }; - let extra_fields = buf_reader.read_vec(cdr.extra_field_len as usize)?; + let extra_fields = cd_reader.read_vec(cdr.extra_field_len as usize)?; - let comment = buf_reader.read_vec(cdr.comment_len as usize)?; + let comment = cd_reader.read_vec(cdr.comment_len as usize)?; let comment = if bit_flag.is_utf8() { String::from_utf8(comment).map_err(|_| ZipError::InvalidFileComment)? } else { -- cgit v1.2.3