Make santized_name part of the library
It is a common pitfall to use the name as-is during extraction. Adding this function may prevent some of the issues. Resolves #65
This commit is contained in:
parent
ce4104d682
commit
5e8c95e6ed
3 changed files with 49 additions and 19 deletions
|
@ -20,7 +20,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 = sanitize_filename(file.name());
|
let outpath = file.sanitized_name();
|
||||||
|
|
||||||
{
|
{
|
||||||
let comment = file.comment();
|
let comment = file.comment();
|
||||||
|
@ -55,21 +55,3 @@ fn real_main() -> i32 {
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sanitize_filename(filename: &str) -> std::path::PathBuf {
|
|
||||||
let no_null_filename = match filename.find('\0') {
|
|
||||||
Some(index) => &filename[0..index],
|
|
||||||
None => filename,
|
|
||||||
};
|
|
||||||
|
|
||||||
std::path::Path::new(no_null_filename)
|
|
||||||
.components()
|
|
||||||
.filter(|component| match *component {
|
|
||||||
std::path::Component::Normal(..) => true,
|
|
||||||
_ => false,
|
|
||||||
})
|
|
||||||
.fold(std::path::PathBuf::new(), |mut path, ref cur| {
|
|
||||||
path.push(cur.as_os_str());
|
|
||||||
path
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
|
@ -415,6 +415,11 @@ impl<'a> ZipFile<'a> {
|
||||||
pub fn name_raw(&self) -> &[u8] {
|
pub fn name_raw(&self) -> &[u8] {
|
||||||
&*self.data.file_name_raw
|
&*self.data.file_name_raw
|
||||||
}
|
}
|
||||||
|
/// Get the name of the file in a sanitized form. It truncates the name to the first NULL byte,
|
||||||
|
/// removes a leading '/' and removes '..' parts.
|
||||||
|
pub fn sanitized_name(&self) -> ::std::path::PathBuf {
|
||||||
|
self.data.file_name_sanitized()
|
||||||
|
}
|
||||||
/// Get the comment of the file
|
/// Get the comment of the file
|
||||||
pub fn comment(&self) -> &str {
|
pub fn comment(&self) -> &str {
|
||||||
&*self.data.file_comment
|
&*self.data.file_comment
|
||||||
|
|
43
src/types.rs
43
src/types.rs
|
@ -61,6 +61,26 @@ pub struct ZipFileData
|
||||||
pub external_attributes: u32,
|
pub external_attributes: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ZipFileData {
|
||||||
|
pub fn file_name_sanitized(&self) -> ::std::path::PathBuf {
|
||||||
|
let no_null_filename = match self.file_name.find('\0') {
|
||||||
|
Some(index) => &self.file_name[0..index],
|
||||||
|
None => &self.file_name,
|
||||||
|
};
|
||||||
|
|
||||||
|
::std::path::Path::new(no_null_filename)
|
||||||
|
.components()
|
||||||
|
.filter(|component| match *component {
|
||||||
|
::std::path::Component::Normal(..) => true,
|
||||||
|
_ => false,
|
||||||
|
})
|
||||||
|
.fold(::std::path::PathBuf::new(), |mut path, ref cur| {
|
||||||
|
path.push(cur.as_os_str());
|
||||||
|
path
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -71,4 +91,27 @@ mod test {
|
||||||
assert_eq!(System::from_u8(0), System::Dos);
|
assert_eq!(System::from_u8(0), System::Dos);
|
||||||
assert_eq!(System::from_u8(3), System::Unix);
|
assert_eq!(System::from_u8(3), System::Unix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sanitize() {
|
||||||
|
use super::*;
|
||||||
|
let file_name = "/path/../../../../etc/./passwd\0/etc/shadow".to_string();
|
||||||
|
let data = ZipFileData {
|
||||||
|
system: System::Dos,
|
||||||
|
version_made_by: 0,
|
||||||
|
encrypted: false,
|
||||||
|
compression_method: ::compression::CompressionMethod::Stored,
|
||||||
|
last_modified_time: time::empty_tm(),
|
||||||
|
crc32: 0,
|
||||||
|
compressed_size: 0,
|
||||||
|
uncompressed_size: 0,
|
||||||
|
file_name: file_name.clone(),
|
||||||
|
file_name_raw: file_name.into_bytes(),
|
||||||
|
file_comment: String::new(),
|
||||||
|
header_start: 0,
|
||||||
|
data_start: 0,
|
||||||
|
external_attributes: 0,
|
||||||
|
};
|
||||||
|
assert_eq!(data.file_name_sanitized().to_str().unwrap(), "path/etc/passwd");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue