test: Fix a bug involving ZIP64 field parsing
This commit is contained in:
parent
499bd65f71
commit
c4bd7a61a5
2 changed files with 18 additions and 7 deletions
17
src/read.rs
17
src/read.rs
|
@ -20,6 +20,7 @@ use std::ffi::OsString;
|
||||||
use std::fs::create_dir_all;
|
use std::fs::create_dir_all;
|
||||||
use std::io::{self, copy, prelude::*, sink, SeekFrom};
|
use std::io::{self, copy, prelude::*, sink, SeekFrom};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
use std::mem::size_of;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::sync::{Arc, OnceLock};
|
use std::sync::{Arc, OnceLock};
|
||||||
|
@ -94,7 +95,7 @@ use crate::aes::PWD_VERIFY_LENGTH;
|
||||||
use crate::extra_fields::UnicodeExtraField;
|
use crate::extra_fields::UnicodeExtraField;
|
||||||
#[cfg(feature = "lzma")]
|
#[cfg(feature = "lzma")]
|
||||||
use crate::read::lzma::LzmaDecoder;
|
use crate::read::lzma::LzmaDecoder;
|
||||||
use crate::result::ZipError::{InvalidPassword, UnsupportedArchive};
|
use crate::result::ZipError::{InvalidArchive, InvalidPassword, UnsupportedArchive};
|
||||||
use crate::spec::is_dir;
|
use crate::spec::is_dir;
|
||||||
use crate::types::ffi::S_IFLNK;
|
use crate::types::ffi::S_IFLNK;
|
||||||
use crate::unstable::{path_to_string, LittleEndianReadExt};
|
use crate::unstable::{path_to_string, LittleEndianReadExt};
|
||||||
|
@ -1233,17 +1234,25 @@ pub(crate) fn parse_single_extra_field<R: Read>(
|
||||||
match kind {
|
match kind {
|
||||||
// Zip64 extended information extra field
|
// Zip64 extended information extra field
|
||||||
0x0001 => {
|
0x0001 => {
|
||||||
if file.uncompressed_size == spec::ZIP64_BYTES_THR {
|
let mut consumed_len = 0;
|
||||||
|
if len >= 24 || file.uncompressed_size == spec::ZIP64_BYTES_THR {
|
||||||
file.large_file = true;
|
file.large_file = true;
|
||||||
file.uncompressed_size = reader.read_u64_le()?;
|
file.uncompressed_size = reader.read_u64_le()?;
|
||||||
|
consumed_len += size_of::<u64>();
|
||||||
}
|
}
|
||||||
if file.compressed_size == spec::ZIP64_BYTES_THR {
|
if len >= 24 || file.compressed_size == spec::ZIP64_BYTES_THR {
|
||||||
file.large_file = true;
|
file.large_file = true;
|
||||||
file.compressed_size = reader.read_u64_le()?;
|
file.compressed_size = reader.read_u64_le()?;
|
||||||
|
consumed_len += size_of::<u64>();
|
||||||
}
|
}
|
||||||
if file.header_start == spec::ZIP64_BYTES_THR {
|
if len >= 24 || file.header_start == spec::ZIP64_BYTES_THR {
|
||||||
file.header_start = reader.read_u64_le()?;
|
file.header_start = reader.read_u64_le()?;
|
||||||
|
consumed_len += size_of::<u64>();
|
||||||
}
|
}
|
||||||
|
let Some(leftover_len) = (len as usize).checked_sub(consumed_len) else {
|
||||||
|
return Err(InvalidArchive("ZIP64 extra-data field is the wrong length"));
|
||||||
|
};
|
||||||
|
reader.read_exact(&mut vec![0u8; leftover_len])?;
|
||||||
}
|
}
|
||||||
0x9901 => {
|
0x9901 => {
|
||||||
// AES
|
// AES
|
||||||
|
|
|
@ -325,11 +325,12 @@ impl ExtendedFileOptions {
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
let mut data = Cursor::new(data);
|
let mut data = Cursor::new(data);
|
||||||
while data.position() < len {
|
let mut pos = data.position();
|
||||||
|
while pos < len {
|
||||||
if len - data.position() < 4 {
|
if len - data.position() < 4 {
|
||||||
return Err(ZipError::Io(io::Error::new(
|
return Err(ZipError::Io(io::Error::new(
|
||||||
io::ErrorKind::Other,
|
io::ErrorKind::Other,
|
||||||
"Extra-data field doesn't have room for tag and length",
|
"Extra-data field doesn't have room for ID and length",
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "unreserved"))]
|
#[cfg(not(feature = "unreserved"))]
|
||||||
|
@ -350,7 +351,8 @@ impl ExtendedFileOptions {
|
||||||
}
|
}
|
||||||
data.seek(SeekFrom::Current(-2))?;
|
data.seek(SeekFrom::Current(-2))?;
|
||||||
}
|
}
|
||||||
parse_single_extra_field(&mut ZipFileData::default(), &mut data, 0)?;
|
parse_single_extra_field(&mut ZipFileData::default(), &mut data, pos)?;
|
||||||
|
pos = data.position();
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue