mirror of
https://github.com/mimblewimble/grin.git
synced 2025-02-08 04:11:08 +03:00
catch the panic to avoid peer thread quit early (#2686)
* catch the panic to avoid peer thread quit before taking the chance to ban * move catch wrapper logic down into the util crate * log the panic info * keep txhashset.rs untouched * remove a warning
This commit is contained in:
parent
148256de6e
commit
32d939189d
1 changed files with 68 additions and 45 deletions
113
util/src/zip.rs
113
util/src/zip.rs
|
@ -15,6 +15,7 @@
|
||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
/// Wrappers around the `zip-rs` library to compress and decompress zip archives.
|
/// Wrappers around the `zip-rs` library to compress and decompress zip archives.
|
||||||
use std::io;
|
use std::io;
|
||||||
|
use std::panic;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use walkdir::WalkDir;
|
use walkdir::WalkDir;
|
||||||
|
|
||||||
|
@ -64,58 +65,80 @@ pub fn compress(src_dir: &Path, dst_file: &File) -> ZipResult<()> {
|
||||||
/// Decompress a source file into the provided destination path.
|
/// Decompress a source file into the provided destination path.
|
||||||
pub fn decompress<R, F>(src_file: R, dest: &Path, expected: F) -> ZipResult<usize>
|
pub fn decompress<R, F>(src_file: R, dest: &Path, expected: F) -> ZipResult<usize>
|
||||||
where
|
where
|
||||||
R: io::Read + io::Seek,
|
R: io::Read + io::Seek + panic::UnwindSafe,
|
||||||
F: Fn(&Path) -> bool,
|
F: Fn(&Path) -> bool + panic::UnwindSafe,
|
||||||
{
|
{
|
||||||
let mut decompressed = 0;
|
let mut decompressed = 0;
|
||||||
let mut archive = zip_rs::ZipArchive::new(src_file)?;
|
|
||||||
|
|
||||||
for i in 0..archive.len() {
|
// catch the panic to avoid the thread quit
|
||||||
let mut file = archive.by_index(i)?;
|
panic::set_hook(Box::new(|panic_info| {
|
||||||
let san_name = file.sanitized_name();
|
error!(
|
||||||
if san_name.to_str().unwrap_or("").replace("\\", "/") != file.name().replace("\\", "/")
|
"panic occurred: {:?}",
|
||||||
|| !expected(&san_name)
|
panic_info.payload().downcast_ref::<&str>().unwrap()
|
||||||
{
|
);
|
||||||
info!(
|
}));
|
||||||
"ignoring a suspicious file: {}, got {:?}",
|
let result = panic::catch_unwind(move || {
|
||||||
file.name(),
|
let mut archive = zip_rs::ZipArchive::new(src_file)?;
|
||||||
san_name.to_str()
|
|
||||||
);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let file_path = dest.join(san_name);
|
|
||||||
|
|
||||||
if (&*file.name()).ends_with('/') {
|
for i in 0..archive.len() {
|
||||||
fs::create_dir_all(&file_path)?;
|
let mut file = archive.by_index(i)?;
|
||||||
} else {
|
let san_name = file.sanitized_name();
|
||||||
if let Some(p) = file_path.parent() {
|
if san_name.to_str().unwrap_or("").replace("\\", "/") != file.name().replace("\\", "/")
|
||||||
if !p.exists() {
|
|| !expected(&san_name)
|
||||||
fs::create_dir_all(&p)?;
|
{
|
||||||
|
info!(
|
||||||
|
"ignoring a suspicious file: {}, got {:?}",
|
||||||
|
file.name(),
|
||||||
|
san_name.to_str()
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let file_path = dest.join(san_name);
|
||||||
|
|
||||||
|
if (&*file.name()).ends_with('/') {
|
||||||
|
fs::create_dir_all(&file_path)?;
|
||||||
|
} else {
|
||||||
|
if let Some(p) = file_path.parent() {
|
||||||
|
if !p.exists() {
|
||||||
|
fs::create_dir_all(&p)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let res = fs::File::create(&file_path);
|
||||||
|
let mut outfile = match res {
|
||||||
|
Err(e) => {
|
||||||
|
error!("{:?}", e);
|
||||||
|
return Err(zip::result::ZipError::Io(e));
|
||||||
|
}
|
||||||
|
Ok(r) => r,
|
||||||
|
};
|
||||||
|
io::copy(&mut file, &mut outfile)?;
|
||||||
|
decompressed += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get and Set permissions
|
||||||
|
#[cfg(unix)]
|
||||||
|
{
|
||||||
|
use std::os::unix::fs::PermissionsExt;
|
||||||
|
if let Some(mode) = file.unix_mode() {
|
||||||
|
fs::set_permissions(
|
||||||
|
&file_path.to_str().unwrap(),
|
||||||
|
PermissionsExt::from_mode(mode),
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let res = fs::File::create(&file_path);
|
|
||||||
let mut outfile = match res {
|
|
||||||
Err(e) => {
|
|
||||||
error!("{:?}", e);
|
|
||||||
return Err(zip::result::ZipError::Io(e));
|
|
||||||
}
|
|
||||||
Ok(r) => r,
|
|
||||||
};
|
|
||||||
io::copy(&mut file, &mut outfile)?;
|
|
||||||
decompressed += 1;
|
|
||||||
}
|
}
|
||||||
|
Ok(decompressed)
|
||||||
// Get and Set permissions
|
});
|
||||||
#[cfg(unix)]
|
match result {
|
||||||
{
|
Ok(res) => match res {
|
||||||
use std::os::unix::fs::PermissionsExt;
|
Err(e) => Err(e.into()),
|
||||||
if let Some(mode) = file.unix_mode() {
|
Ok(_) => res,
|
||||||
fs::set_permissions(
|
},
|
||||||
&file_path.to_str().unwrap(),
|
Err(_) => {
|
||||||
PermissionsExt::from_mode(mode),
|
error!("panic occurred on zip::decompress!");
|
||||||
)?;
|
Err(zip::result::ZipError::InvalidArchive(
|
||||||
}
|
"panic occurred on zip::decompress",
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(decompressed)
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue