docs: improve explanation of new APIs
This commit is contained in:
parent
33a787ec54
commit
105368aebf
5 changed files with 14 additions and 19 deletions
|
@ -18,7 +18,7 @@ fn real_main() -> i32 {
|
||||||
|
|
||||||
for i in 0..archive.len() {
|
for i in 0..archive.len() {
|
||||||
let mut file = archive.by_index(i).unwrap();
|
let mut file = archive.by_index(i).unwrap();
|
||||||
let outpath = match file.name_as_child() {
|
let outpath = match file.enclosed_name() {
|
||||||
Some(path) => path.to_owned(),
|
Some(path) => path.to_owned(),
|
||||||
None => continue,
|
None => continue,
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,7 +19,7 @@ fn real_main() -> i32 {
|
||||||
|
|
||||||
for i in 0..archive.len() {
|
for i in 0..archive.len() {
|
||||||
let file = archive.by_index(i).unwrap();
|
let file = archive.by_index(i).unwrap();
|
||||||
let outpath = match file.name_as_child() {
|
let outpath = match file.enclosed_name() {
|
||||||
Some(path) => path,
|
Some(path) => path,
|
||||||
None => {
|
None => {
|
||||||
println!("Entry {} has a suspicious path", file.name());
|
println!("Entry {} has a suspicious path", file.name());
|
||||||
|
|
25
src/read.rs
25
src/read.rs
|
@ -311,28 +311,23 @@ impl<R: Read + io::Seek> ZipArchive<R> {
|
||||||
comment: footer.zip_file_comment,
|
comment: footer.zip_file_comment,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
/// Extract a Zip archive into a directory.
|
/// Extract a Zip archive into a directory, overwriting files if they
|
||||||
|
/// already exist. Paths are sanitized with [`ZipFile::enclosed_name`].
|
||||||
///
|
///
|
||||||
/// Malformed and malicious paths are rejected so that they cannot escape
|
/// Extraction is not atomic; If an error is encountered, some of the files
|
||||||
/// the given directory.
|
/// may be left on disk.
|
||||||
///
|
|
||||||
/// This bails on the first error and does not attempt cleanup.
|
|
||||||
///
|
|
||||||
/// # Platform-specific behaviour
|
|
||||||
///
|
|
||||||
/// On unix systems permissions from the zip file are preserved, if they exist.
|
|
||||||
pub fn extract<P: AsRef<Path>>(&mut self, directory: P) -> ZipResult<()> {
|
pub fn extract<P: AsRef<Path>>(&mut self, directory: P) -> ZipResult<()> {
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
|
||||||
for i in 0..self.len() {
|
for i in 0..self.len() {
|
||||||
let mut file = self.by_index(i)?;
|
let mut file = self.by_index(i)?;
|
||||||
let filepath = file
|
let filepath = file
|
||||||
.name_as_child()
|
.enclosed_name()
|
||||||
.ok_or(ZipError::InvalidArchive("Invalid file path"))?;
|
.ok_or(ZipError::InvalidArchive("Invalid file path"))?;
|
||||||
|
|
||||||
let outpath = directory.as_ref().join(filepath);
|
let outpath = directory.as_ref().join(filepath);
|
||||||
|
|
||||||
if (file.name()).ends_with('/') {
|
if file.name().ends_with('/') {
|
||||||
fs::create_dir_all(&outpath)?;
|
fs::create_dir_all(&outpath)?;
|
||||||
} else {
|
} else {
|
||||||
if let Some(p) = outpath.parent() {
|
if let Some(p) = outpath.parent() {
|
||||||
|
@ -617,7 +612,7 @@ impl<'a> ZipFile<'a> {
|
||||||
/// allows an attacker to craft a ZIP archive that will overwrite critical
|
/// allows an attacker to craft a ZIP archive that will overwrite critical
|
||||||
/// files.
|
/// files.
|
||||||
///
|
///
|
||||||
/// You can use the [`ZipFile::name_as_child`] method to validate the name
|
/// You can use the [`ZipFile::enclosed_name`] method to validate the name
|
||||||
/// as a safe path.
|
/// as a safe path.
|
||||||
pub fn name(&self) -> &str {
|
pub fn name(&self) -> &str {
|
||||||
&self.data.file_name
|
&self.data.file_name
|
||||||
|
@ -650,7 +645,7 @@ impl<'a> ZipFile<'a> {
|
||||||
/// This is appropriate if you need to be able to extract *something* from
|
/// This is appropriate if you need to be able to extract *something* from
|
||||||
/// any archive, but will easily misrepresent trivial paths like
|
/// any archive, but will easily misrepresent trivial paths like
|
||||||
/// `foo/../bar` as `foo/bar` (instead of `bar`). Because of this,
|
/// `foo/../bar` as `foo/bar` (instead of `bar`). Because of this,
|
||||||
/// [`ZipFile::name_as_child`] is the better option in most scenarios.
|
/// [`ZipFile::enclosed_name`] is the better option in most scenarios.
|
||||||
///
|
///
|
||||||
/// [`ParentDir`]: `Component::ParentDir`
|
/// [`ParentDir`]: `Component::ParentDir`
|
||||||
pub fn mangled_name(&self) -> ::std::path::PathBuf {
|
pub fn mangled_name(&self) -> ::std::path::PathBuf {
|
||||||
|
@ -667,7 +662,7 @@ impl<'a> ZipFile<'a> {
|
||||||
/// This will read well-formed ZIP files correctly, and is resistant
|
/// This will read well-formed ZIP files correctly, and is resistant
|
||||||
/// to path-based exploits. It is recommended over
|
/// to path-based exploits. It is recommended over
|
||||||
/// [`ZipFile::mangled_name`].
|
/// [`ZipFile::mangled_name`].
|
||||||
pub fn name_as_child(&self) -> Option<&Path> {
|
pub fn enclosed_name(&self) -> Option<&Path> {
|
||||||
if self.data.file_name.contains('\0') {
|
if self.data.file_name.contains('\0') {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
@ -1010,7 +1005,7 @@ mod test {
|
||||||
|
|
||||||
for i in 0..zip.len() {
|
for i in 0..zip.len() {
|
||||||
let zip_file = zip.by_index(i).unwrap();
|
let zip_file = zip.by_index(i).unwrap();
|
||||||
let full_name = zip_file.name_as_child().unwrap();
|
let full_name = zip_file.enclosed_name().unwrap();
|
||||||
let file_name = full_name.file_name().unwrap().to_str().unwrap();
|
let file_name = full_name.file_name().unwrap().to_str().unwrap();
|
||||||
assert!(
|
assert!(
|
||||||
(file_name.starts_with("dir") && zip_file.is_dir())
|
(file_name.starts_with("dir") && zip_file.is_dir())
|
||||||
|
|
|
@ -195,7 +195,7 @@ fn zip64_large() {
|
||||||
|
|
||||||
for i in 0..archive.len() {
|
for i in 0..archive.len() {
|
||||||
let mut file = archive.by_index(i).unwrap();
|
let mut file = archive.by_index(i).unwrap();
|
||||||
let outpath = file.name_as_child().unwrap();
|
let outpath = file.enclosed_name().unwrap();
|
||||||
println!(
|
println!(
|
||||||
"Entry {} has name \"{}\" ({} bytes)",
|
"Entry {} has name \"{}\" ({} bytes)",
|
||||||
i,
|
i,
|
||||||
|
|
|
@ -75,7 +75,7 @@ fn encrypted_file() {
|
||||||
.by_index_decrypt(0, "test".as_bytes())
|
.by_index_decrypt(0, "test".as_bytes())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let file_name = file.name_as_child().unwrap();
|
let file_name = file.enclosed_name().unwrap();
|
||||||
assert_eq!(file_name, std::path::PathBuf::from("test.txt"));
|
assert_eq!(file_name, std::path::PathBuf::from("test.txt"));
|
||||||
|
|
||||||
let mut data = Vec::new();
|
let mut data = Vec::new();
|
||||||
|
|
Loading…
Add table
Reference in a new issue