Skip to content
Snippets Groups Projects
Commit 0627b46f authored by Jason Volk's avatar Jason Volk
Browse files

add panic suite to Error


Signed-off-by: default avatarJason Volk <jason@zemos.net>
parent f10f5319
No related branches found
No related tags found
1 merge request!520Panic / Error Handling
...@@ -84,7 +84,7 @@ pub(crate) async fn send_transaction_message_route( ...@@ -84,7 +84,7 @@ pub(crate) async fn send_transaction_message_route(
Ok(send_transaction_message::v1::Response { Ok(send_transaction_message::v1::Response {
pdus: resolved_map pdus: resolved_map
.into_iter() .into_iter()
.map(|(e, r)| (e, r.map_err(|e| e.sanitized_error()))) .map(|(e, r)| (e, r.map_err(|e| e.sanitized_string())))
.collect(), .collect(),
}) })
} }
......
#![allow(dead_code)] // this is a developer's toolbox use std::{any::Any, panic};
use std::panic;
/// Export all of the ancillary tools from here as well. /// Export all of the ancillary tools from here as well.
pub use crate::utils::debug::*; pub use crate::utils::debug::*;
...@@ -79,3 +77,6 @@ pub fn trap() { ...@@ -79,3 +77,6 @@ pub fn trap() {
std::arch::asm!("int3"); std::arch::asm!("int3");
} }
} }
#[must_use]
pub fn panic_str(p: &Box<dyn Any + Send>) -> &'static str { p.downcast_ref::<&str>().copied().unwrap_or_default() }
use std::{convert::Infallible, fmt}; use std::{
any::Any,
convert::Infallible,
fmt,
panic::{RefUnwindSafe, UnwindSafe},
};
use bytes::BytesMut; use bytes::BytesMut;
use http::StatusCode; use http::StatusCode;
...@@ -8,10 +13,15 @@ ...@@ -8,10 +13,15 @@
OwnedServerName, OwnedServerName,
}; };
use crate::{debug_error, error}; use crate::{debug::panic_str, debug_error, error};
#[derive(thiserror::Error)] #[derive(thiserror::Error)]
pub enum Error { pub enum Error {
#[error("PANIC!")]
PanicAny(Box<dyn Any + Send>),
#[error("PANIC! {0}")]
Panic(&'static str, Box<dyn Any + Send + 'static>),
// std // std
#[error("{0}")] #[error("{0}")]
Fmt(#[from] fmt::Error), Fmt(#[from] fmt::Error),
...@@ -31,6 +41,8 @@ pub enum Error { ...@@ -31,6 +41,8 @@ pub enum Error {
ParseFloatError(#[from] std::num::ParseFloatError), ParseFloatError(#[from] std::num::ParseFloatError),
// third-party // third-party
#[error("Join error: {0}")]
JoinError(#[from] tokio::task::JoinError),
#[error("Regex error: {0}")] #[error("Regex error: {0}")]
Regex(#[from] regex::Error), Regex(#[from] regex::Error),
#[error("Tracing filter error: {0}")] #[error("Tracing filter error: {0}")]
...@@ -94,6 +106,29 @@ pub fn bad_config(message: &str) -> Self { ...@@ -94,6 +106,29 @@ pub fn bad_config(message: &str) -> Self {
Self::BadConfig(message.to_owned()) Self::BadConfig(message.to_owned())
} }
#[must_use]
pub fn from_panic(e: Box<dyn Any + Send>) -> Self { Self::Panic(panic_str(&e), e) }
pub fn into_panic(self) -> Box<dyn Any + Send + 'static> {
match self {
Self::Panic(_, e) | Self::PanicAny(e) => e,
Self::JoinError(e) => e.into_panic(),
_ => std::panic::panic_any(self),
}
}
/// Sanitizes public-facing errors that can leak sensitive information.
pub fn sanitized_string(&self) -> String {
match self {
Self::Database(..) => String::from("Database error occurred."),
Self::Io(..) => String::from("I/O error occurred."),
_ => self.to_string(),
}
}
/// Get the panic message string.
pub fn panic_str(self) -> Option<&'static str> { self.is_panic().then_some(panic_str(&self.into_panic())) }
/// Returns the Matrix error code / error kind /// Returns the Matrix error code / error kind
#[inline] #[inline]
pub fn error_code(&self) -> ruma::api::client::error::ErrorKind { pub fn error_code(&self) -> ruma::api::client::error::ErrorKind {
...@@ -106,16 +141,28 @@ pub fn error_code(&self) -> ruma::api::client::error::ErrorKind { ...@@ -106,16 +141,28 @@ pub fn error_code(&self) -> ruma::api::client::error::ErrorKind {
} }
} }
/// Sanitizes public-facing errors that can leak sensitive information. /// Check if the Error is trafficking a panic object.
pub fn sanitized_error(&self) -> String { #[inline]
match self { pub fn is_panic(&self) -> bool {
Self::Database(..) => String::from("Database error occurred."), match &self {
Self::Io(..) => String::from("I/O error occurred."), Self::Panic(..) | Self::PanicAny(..) => true,
_ => self.to_string(), Self::JoinError(e) => e.is_panic(),
_ => false,
} }
} }
} }
impl UnwindSafe for Error {}
impl RefUnwindSafe for Error {}
impl From<Infallible> for Error {
fn from(i: Infallible) -> Self { match i {} }
}
impl fmt::Debug for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{self}") }
}
#[inline] #[inline]
pub fn else_log<T, E>(error: E) -> Result<T, Infallible> pub fn else_log<T, E>(error: E) -> Result<T, Infallible>
where where
...@@ -186,14 +233,6 @@ pub fn inspect_debug_log<E: fmt::Debug>(error: &E) { ...@@ -186,14 +233,6 @@ pub fn inspect_debug_log<E: fmt::Debug>(error: &E) {
debug_error!("{error:?}"); debug_error!("{error:?}");
} }
impl fmt::Debug for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{self}") }
}
impl From<Infallible> for Error {
fn from(i: Infallible) -> Self { match i {} }
}
impl axum::response::IntoResponse for Error { impl axum::response::IntoResponse for Error {
fn into_response(self) -> axum::response::Response { fn into_response(self) -> axum::response::Response {
let response: UiaaResponse = self.into(); let response: UiaaResponse = self.into();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment