1
0
mirror of https://github.com/actix/actix-extras.git synced 2024-12-01 02:44:37 +01:00

Fix some unsoundness

This improves the sound implementation of `fn route`.
Previously this function would iterate twice but we
can reduce the overhead without using `unsafe`.
This commit is contained in:
Jef 2018-06-20 10:50:56 +02:00
parent 2f917f3700
commit 234c60d473
3 changed files with 49 additions and 31 deletions

View File

@ -335,33 +335,34 @@ where
T: FromRequest<S> + 'static, T: FromRequest<S> + 'static,
{ {
{ {
let parts = self.parts.as_mut().expect("Use after finish"); let parts: &mut ApplicationParts<S> = self.parts.as_mut().expect("Use after finish");
// get resource handler let out = {
let mut found = false; // get resource handler
for &mut (ref pattern, ref handler) in &mut parts.resources { let mut iterator = parts.resources.iter_mut();
if handler.is_some() && pattern.pattern() == path {
found = true;
break;
}
}
if !found { loop {
let mut handler = ResourceHandler::default(); if let Some(&mut (ref pattern, ref mut handler)) = iterator.next() {
handler.method(method).with(f); if let Some(ref mut handler) = *handler {
let pattern = Resource::new(handler.get_name(), path); if pattern.pattern() == path {
parts.resources.push((pattern, Some(handler))); handler.method(method).with(f);
} else { break None;
for &mut (ref pattern, ref mut handler) in &mut parts.resources { }
if let Some(ref mut handler) = *handler {
if pattern.pattern() == path {
handler.method(method).with(f);
break;
} }
} else {
let mut handler = ResourceHandler::default();
handler.method(method).with(f);
let pattern = Resource::new(handler.get_name(), path);
break Some((pattern, Some(handler)));
} }
} }
};
if let Some(out) = out {
parts.resources.push(out);
} }
} }
self self
} }

View File

@ -1,5 +1,5 @@
//! Multipart requests support //! Multipart requests support
use std::cell::RefCell; use std::cell::{RefCell, UnsafeCell};
use std::marker::PhantomData; use std::marker::PhantomData;
use std::rc::Rc; use std::rc::Rc;
use std::{cmp, fmt}; use std::{cmp, fmt};
@ -590,7 +590,7 @@ where
} }
struct PayloadRef<S> { struct PayloadRef<S> {
payload: Rc<PayloadHelper<S>>, payload: Rc<UnsafeCell<PayloadHelper<S>>>,
} }
impl<S> PayloadRef<S> impl<S> PayloadRef<S>
@ -599,7 +599,7 @@ where
{ {
fn new(payload: PayloadHelper<S>) -> PayloadRef<S> { fn new(payload: PayloadHelper<S>) -> PayloadRef<S> {
PayloadRef { PayloadRef {
payload: Rc::new(payload), payload: Rc::new(payload.into()),
} }
} }
@ -609,7 +609,7 @@ where
{ {
if s.current() { if s.current() {
let payload: &mut PayloadHelper<S> = let payload: &mut PayloadHelper<S> =
unsafe { &mut *(self.payload.as_ref() as *const _ as *mut _) }; unsafe { &mut *self.payload.get() };
Some(payload) Some(payload)
} else { } else {
None None

View File

@ -73,12 +73,11 @@ impl<T: AsyncWrite, H: 'static> H1Writer<T, H> {
self.flags.contains(Flags::KEEPALIVE) && !self.flags.contains(Flags::UPGRADE) self.flags.contains(Flags::KEEPALIVE) && !self.flags.contains(Flags::UPGRADE)
} }
fn write_data(&mut self, data: &[u8]) -> io::Result<usize> { fn write_data(stream: &mut T, data: &[u8]) -> io::Result<usize> {
let mut written = 0; let mut written = 0;
while written < data.len() { while written < data.len() {
match self.stream.write(&data[written..]) { match stream.write(&data[written..]) {
Ok(0) => { Ok(0) => {
self.disconnected();
return Err(io::Error::new(io::ErrorKind::WriteZero, "")); return Err(io::Error::new(io::ErrorKind::WriteZero, ""));
} }
Ok(n) => { Ok(n) => {
@ -243,7 +242,16 @@ impl<T: AsyncWrite, H: 'static> Writer for H1Writer<T, H> {
if self.flags.contains(Flags::UPGRADE) { if self.flags.contains(Flags::UPGRADE) {
if self.buffer.is_empty() { if self.buffer.is_empty() {
let pl: &[u8] = payload.as_ref(); let pl: &[u8] = payload.as_ref();
let n = self.write_data(pl)?; let n = match Self::write_data(&mut self.stream, pl) {
Err(err) => {
if err.kind() == io::ErrorKind::WriteZero {
self.disconnected();
}
return Err(err);
}
Ok(val) => val,
};
if n < pl.len() { if n < pl.len() {
self.buffer.extend_from_slice(&pl[n..]); self.buffer.extend_from_slice(&pl[n..]);
return Ok(WriterState::Done); return Ok(WriterState::Done);
@ -284,9 +292,18 @@ impl<T: AsyncWrite, H: 'static> Writer for H1Writer<T, H> {
#[inline] #[inline]
fn poll_completed(&mut self, shutdown: bool) -> Poll<(), io::Error> { fn poll_completed(&mut self, shutdown: bool) -> Poll<(), io::Error> {
if !self.buffer.is_empty() { if !self.buffer.is_empty() {
let buf: &[u8] = let written = {
unsafe { &mut *(self.buffer.as_ref() as *const _ as *mut _) }; match Self::write_data(&mut self.stream, self.buffer.as_ref()) {
let written = self.write_data(buf)?; Err(err) => {
if err.kind() == io::ErrorKind::WriteZero {
self.disconnected();
}
return Err(err);
}
Ok(val) => val,
}
};
let _ = self.buffer.split_to(written); let _ = self.buffer.split_to(written);
if shutdown && !self.buffer.is_empty() if shutdown && !self.buffer.is_empty()
|| (self.buffer.len() > self.buffer_capacity) || (self.buffer.len() > self.buffer_capacity)