diff --git a/src/read.rs b/src/read.rs index 39686012d..8f0461d98 100644 --- a/src/read.rs +++ b/src/read.rs @@ -323,10 +323,7 @@ pub(crate) fn find_content<'a>( reader: &'a mut (impl Read + Seek), ) -> ZipResult> { // TODO: use .get_or_try_init() once stabilized to provide a closure returning a Result! - let data_start = match data.data_start.get() { - Some(data_start) => *data_start, - None => find_data_start(data, reader)?, - }; + let data_start = data.data_start(reader)?; reader.seek(SeekFrom::Start(data_start))?; Ok((reader as &mut dyn Read).take(data.compressed_size)) @@ -337,14 +334,14 @@ fn find_content_seek<'a, R: Read + Seek>( reader: &'a mut R, ) -> ZipResult> { // Parse local header - let data_start = find_data_start(data, reader)?; + let data_start = data.data_start(reader)?; reader.seek(SeekFrom::Start(data_start))?; // Explicit Ok and ? are needed to convert io::Error to ZipError Ok(SeekableTake::new(reader, data.compressed_size)?) } -fn find_data_start( +pub(crate) fn find_data_start( data: &ZipFileData, reader: &mut (impl Read + Seek + Sized), ) -> Result { @@ -1068,14 +1065,6 @@ pub(crate) fn central_header_to_zip_file( )); } - let data_start = find_data_start(&file, reader)?; - - if data_start > central_directory.directory_start { - return Err(InvalidArchive( - "File data can't start after the central directory", - )); - } - reader.seek(SeekFrom::Start(central_header_end))?; Ok(file) } diff --git a/src/types.rs b/src/types.rs index 39933b54b..a9f86d629 100644 --- a/src/types.rs +++ b/src/types.rs @@ -22,10 +22,12 @@ pub(crate) mod ffi { } use crate::extra_fields::ExtraField; +use crate::read::find_data_start; use crate::result::DateTimeRangeError; use crate::spec::is_dir; use crate::types::ffi::S_IFDIR; use crate::{CompressionMethod, ZIP64_BYTES_THR}; +use std::io::{Read, Seek}; #[cfg(feature = "time")] use time::{error::ComponentRange, Date, Month, OffsetDateTime, PrimitiveDateTime, Time}; @@ -488,8 +490,11 @@ pub struct ZipFileData { impl ZipFileData { /// Get the starting offset of the data of the compressed file - pub fn data_start(&self) -> u64 { - *self.data_start.get().unwrap() + pub fn data_start(&self, reader: &mut (impl Read + Seek + Sized)) -> ZipResult { + match self.data_start.get() { + Some(data_start) => Ok(*data_start), + None => Ok(find_data_start(self, reader)?), + } } #[allow(dead_code)] diff --git a/src/write.rs b/src/write.rs index 96b72a2f3..9bec0105b 100644 --- a/src/write.rs +++ b/src/write.rs @@ -673,7 +673,7 @@ impl ZipWriter { let write_position = self.inner.get_plain().stream_position()?; let src_index = self.index_by_name(src_name)?; let src_data = &mut self.files[src_index]; - let src_data_start = src_data.data_start(); + let src_data_start = src_data.data_start(self.inner.get_plain())?; debug_assert!(src_data_start <= write_position); let mut compressed_size = src_data.compressed_size; if compressed_size > (write_position - src_data_start) {