mirror of
https://github.com/actix/actix-web.git
synced 2024-11-27 03:51:10 +00:00
InternalError can trigger memory unsafety #301
This commit is contained in:
parent
b9f6c313d4
commit
a0344eebeb
2 changed files with 25 additions and 18 deletions
30
src/error.rs
30
src/error.rs
|
@ -1,8 +1,8 @@
|
|||
//! Error and Result module
|
||||
use std::cell::RefCell;
|
||||
use std::io::Error as IoError;
|
||||
use std::str::Utf8Error;
|
||||
use std::string::FromUtf8Error;
|
||||
use std::sync::Mutex;
|
||||
use std::{fmt, io, result};
|
||||
|
||||
use actix::MailboxError;
|
||||
|
@ -24,7 +24,7 @@ pub use cookie::ParseError as CookieParseError;
|
|||
|
||||
use handler::Responder;
|
||||
use httprequest::HttpRequest;
|
||||
use httpresponse::HttpResponse;
|
||||
use httpresponse::{HttpResponse, InnerHttpResponse};
|
||||
|
||||
/// A specialized [`Result`](https://doc.rust-lang.org/std/result/enum.Result.html)
|
||||
/// for actix web operations
|
||||
|
@ -80,7 +80,8 @@ impl Error {
|
|||
}
|
||||
}
|
||||
|
||||
/// Attempts to downcast this `Error` to a particular `Fail` type by reference.
|
||||
/// Attempts to downcast this `Error` to a particular `Fail` type by
|
||||
/// reference.
|
||||
///
|
||||
/// If the underlying error is not of type `T`, this will return `None`.
|
||||
pub fn downcast_ref<T: Fail>(&self) -> Option<&T> {
|
||||
|
@ -116,8 +117,8 @@ impl Error {
|
|||
|
||||
/// Helper trait to downcast a response error into a fail.
|
||||
///
|
||||
/// This is currently not exposed because it's unclear if this is the best way to
|
||||
/// achieve the downcasting on `Error` for which this is needed.
|
||||
/// This is currently not exposed because it's unclear if this is the best way
|
||||
/// to achieve the downcasting on `Error` for which this is needed.
|
||||
#[doc(hidden)]
|
||||
pub trait InternalResponseErrorAsFail {
|
||||
#[doc(hidden)]
|
||||
|
@ -190,11 +191,9 @@ impl<T: ResponseError> From<T> for Error {
|
|||
}
|
||||
|
||||
/// Compatibility for `failure::Error`
|
||||
impl<T> ResponseError for failure::Compat<T>
|
||||
where
|
||||
T: fmt::Display + fmt::Debug + Sync + Send + 'static,
|
||||
{
|
||||
}
|
||||
impl<T> ResponseError for failure::Compat<T> where
|
||||
T: fmt::Display + fmt::Debug + Sync + Send + 'static
|
||||
{}
|
||||
|
||||
impl From<failure::Error> for Error {
|
||||
fn from(err: failure::Error) -> Error {
|
||||
|
@ -657,12 +656,9 @@ pub struct InternalError<T> {
|
|||
backtrace: Backtrace,
|
||||
}
|
||||
|
||||
unsafe impl<T> Sync for InternalError<T> {}
|
||||
unsafe impl<T> Send for InternalError<T> {}
|
||||
|
||||
enum InternalErrorType {
|
||||
Status(StatusCode),
|
||||
Response(RefCell<Option<HttpResponse>>),
|
||||
Response(Mutex<Option<Box<InnerHttpResponse>>>),
|
||||
}
|
||||
|
||||
impl<T> InternalError<T> {
|
||||
|
@ -679,7 +675,7 @@ impl<T> InternalError<T> {
|
|||
pub fn from_response(cause: T, response: HttpResponse) -> Self {
|
||||
InternalError {
|
||||
cause,
|
||||
status: InternalErrorType::Response(RefCell::new(Some(response))),
|
||||
status: InternalErrorType::Response(Mutex::new(Some(response.into_inner()))),
|
||||
backtrace: Backtrace::new(),
|
||||
}
|
||||
}
|
||||
|
@ -720,8 +716,8 @@ where
|
|||
match self.status {
|
||||
InternalErrorType::Status(st) => HttpResponse::new(st),
|
||||
InternalErrorType::Response(ref resp) => {
|
||||
if let Some(resp) = resp.borrow_mut().take() {
|
||||
resp
|
||||
if let Some(resp) = resp.lock().unwrap().take() {
|
||||
HttpResponse::from_inner(resp)
|
||||
} else {
|
||||
HttpResponse::new(StatusCode::INTERNAL_SERVER_ERROR)
|
||||
}
|
||||
|
|
|
@ -241,6 +241,14 @@ impl HttpResponse {
|
|||
pub fn set_write_buffer_capacity(&mut self, cap: usize) {
|
||||
self.get_mut().write_capacity = cap;
|
||||
}
|
||||
|
||||
pub(crate) fn into_inner(mut self) -> Box<InnerHttpResponse> {
|
||||
self.0.take().unwrap()
|
||||
}
|
||||
|
||||
pub(crate) fn from_inner(inner: Box<InnerHttpResponse>) -> HttpResponse {
|
||||
HttpResponse(Some(inner), HttpResponsePool::pool())
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for HttpResponse {
|
||||
|
@ -797,7 +805,7 @@ impl<'a, S> From<&'a HttpRequest<S>> for HttpResponseBuilder {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct InnerHttpResponse {
|
||||
pub(crate) struct InnerHttpResponse {
|
||||
version: Option<Version>,
|
||||
headers: HeaderMap,
|
||||
status: StatusCode,
|
||||
|
@ -811,6 +819,9 @@ struct InnerHttpResponse {
|
|||
error: Option<Error>,
|
||||
}
|
||||
|
||||
unsafe impl Sync for InnerHttpResponse {}
|
||||
unsafe impl Send for InnerHttpResponse {}
|
||||
|
||||
impl InnerHttpResponse {
|
||||
#[inline]
|
||||
fn new(status: StatusCode, body: Body) -> InnerHttpResponse {
|
||||
|
|
Loading…
Reference in a new issue