diff options
author | rabite <rabite@posteo.de> | 2020-02-08 00:17:56 +0100 |
---|---|---|
committer | rabite <rabite@posteo.de> | 2020-02-08 00:17:56 +0100 |
commit | e3b4c997bf3f0075c6e1ecb282117d9cade3a440 (patch) | |
tree | d001ff84ecb5a134ce0d982ad38813164ea02aa1 | |
parent | 6afca62010f2b6e7dc4921c4d4aa02ce5e5c3b33 (diff) |
fix crash by catching tree_magic's panic and handle it gracefully
-rw-r--r-- | src/fail.rs | 4 | ||||
-rw-r--r-- | src/files.rs | 53 | ||||
-rw-r--r-- | src/preview.rs | 5 | ||||
-rw-r--r-- | src/quick_actions.rs | 10 | ||||
-rw-r--r-- | src/trait_ext.rs | 2 |
5 files changed, 56 insertions, 18 deletions
diff --git a/src/fail.rs b/src/fail.rs index 1abdea7..36a88d4 100644 --- a/src/fail.rs +++ b/src/fail.rs @@ -382,7 +382,9 @@ pub enum MimeError { #[fail(display = "File access failed! Error: {}", _0)] AccessFailed(Box<HError>), #[fail(display = "No MIME type found for this file",)] - NoMimeFound + NoMimeFound, + #[fail(display = "Paniced while trying to find MIME type for: {}!", _0)] + Panic(String), } impl From<MimeError> for HError { diff --git a/src/files.rs b/src/files.rs index 914f16f..d9f4534 100644 --- a/src/files.rs +++ b/src/files.rs @@ -961,23 +961,52 @@ impl File { Ok((size as u32, unit)) } - pub fn get_mime(&self) -> Option<mime_guess::Mime> { + // Sadly tree_magic tends to panic (in unwraps a None) when called + // with things like pipes, non-existing files. and other stuff. To + // prevent it from crashing hunter it's necessary to catch the + // panic with a custom panic hook and handle it gracefully by just + // doing nothing + pub fn get_mime(&self) -> HResult<mime_guess::Mime> { + use std::panic; + use crate::fail::MimeError; + if let Some(ext) = self.path.extension() { let mime = mime_guess::from_ext(&ext.to_string_lossy()).first(); - mime - } else { - // Fix crash in tree_magic when called on non-regular file - // Also fix crash when a file doesn't exist any more - self.meta() - .and_then(|meta| { - if meta.is_file() && self.path.exists() { - let mime = tree_magic::from_filepath(&self.path); - mime::Mime::from_str(&mime).ok() - } else { None } - }) + if mime.is_some() { + return Ok(mime.unwrap()); + } } + + self.meta() + .map(|meta| { + // Take and replace panic handler which does nothing + let panic_hook = panic::take_hook(); + panic::set_hook(Box::new(|_| {} )); + + // Catch possible panic caused by tree_magic + let mime = panic::catch_unwind(|| { + match meta.is_file() && self.path.exists() { + true => { + let mime = tree_magic::from_filepath(&self.path); + mime::Mime::from_str(&mime).ok() + } + false => None + } + }); + + // Restore previous panic handler + panic::set_hook(panic_hook); + + mime + }).unwrap_or(Ok(None)) + .unwrap_or(None) + .ok_or_else(|| { + let file = self.name.clone(); + HError::Mime(MimeError::Panic(file)) + }) } + pub fn is_text(&self) -> bool { tree_magic::match_filepath("text/plain", &self.path) } diff --git a/src/preview.rs b/src/preview.rs index 0b27176..7e4439a 100644 --- a/src/preview.rs +++ b/src/preview.rs @@ -381,7 +381,10 @@ impl Previewer { return Ok(preview?); } - if let Some(mime) = file.get_mime() { + if let Some(mime) = file.get_mime() + .log_and() + .ok() + { let mime_type = mime.type_().as_str(); let is_gif = mime.subtype() == "gif"; let has_media = core.config().media_available(); diff --git a/src/quick_actions.rs b/src/quick_actions.rs index 8f7fa24..5a08e0e 100644 --- a/src/quick_actions.rs +++ b/src/quick_actions.rs @@ -12,7 +12,7 @@ use std::ffi::OsString; use std::str::FromStr; -use crate::fail::{HResult, HError, KeyBindError}; +use crate::fail::{HResult, HError, KeyBindError, ErrorLog}; use crate::widget::{Widget, WidgetCore, Events}; use crate::foldview::{Foldable, FoldableWidgetExt, ActingExt}; use crate::listview::ListView; @@ -432,12 +432,16 @@ impl QuickFiles for Vec<File> { fn common_mime(&self) -> Option<Mime> { let first_mime = self .get(0)? - .get_mime(); + .get_mime() + .log_and() + .ok(); self.iter() .fold(first_mime, |common_mime, file| { - let cur_mime = file.get_mime(); + let cur_mime = file.get_mime() + .log_and() + .ok(); if &cur_mime == &common_mime { cur_mime diff --git a/src/trait_ext.rs b/src/trait_ext.rs index 90ce6d3..530d1e8 100644 --- a/src/trait_ext.rs +++ b/src/trait_ext.rs @@ -43,6 +43,6 @@ impl PathBufMime for PathBuf { .map(|mime| { Ok(format!("{}", mime)) }) - .ok_or(MimeError::NoMimeFound)? + .map_err(|_| MimeError::NoMimeFound)? } } |