layout: Don't leak FlowRefs to the flexbox layout code.

This can cause memory safety problems. Comments have been added to
`flow_list.rs` to prevent this from happening again.
This commit is contained in:
Patrick Walton 2016-10-24 17:43:12 -07:00
parent 179547b68f
commit d990a7eb84
2 changed files with 100 additions and 76 deletions

View file

@ -5,10 +5,17 @@
use flow::Flow;
use flow_ref::{self, FlowRef};
use std::collections::{LinkedList, linked_list};
use std::ops::{Index, IndexMut};
// This needs to be reworked now that we have dynamically-sized types in Rust.
// Until then, it's just a wrapper around LinkedList.
/// This needs to be reworked now that we have dynamically-sized types in Rust.
/// Until then, it's just a wrapper around LinkedList.
///
/// SECURITY-NOTE(pcwalton): It is very important that `FlowRef` values not leak directly to
/// layout. Layout code must only interact with `&Flow` or `&mut Flow` values. Otherwise, layout
/// could stash `FlowRef` values in random places unknown to the system and thereby cause data
/// races. Those data races can lead to memory safety problems, potentially including arbitrary
/// remote code execution! In general, do not add new methods to this file (e.g. new ways of
/// iterating over flows) unless you are *very* sure of what you are doing.
pub struct FlowList {
flows: LinkedList<FlowRef>,
}
@ -52,13 +59,19 @@ impl FlowList {
}
}
/// Provide a forward iterator
/// Provide a forward iterator.
///
/// SECURITY-NOTE(pcwalton): This does not hand out `FlowRef`s by design. Do not add a method
/// to do so! See the comment above in `FlowList`.
#[inline]
pub fn iter<'a>(&'a self) -> impl DoubleEndedIterator<Item = &'a Flow> {
self.flows.iter().map(|flow| &**flow)
}
/// Provide a forward iterator with mutable references
///
/// SECURITY-NOTE(pcwalton): This does not hand out `FlowRef`s by design. Do not add a method
/// to do so! See the comment above in `FlowList`.
#[inline]
pub fn iter_mut(&mut self) -> MutFlowListIterator {
MutFlowListIterator {
@ -66,13 +79,6 @@ impl FlowList {
}
}
/// Provide a forward iterator with FlowRef items
#[inline]
pub fn iter_flow_ref_mut<'a>(&'a mut self)
-> impl DoubleEndedIterator<Item = &'a mut FlowRef> {
self.flows.iter_mut()
}
/// O(1)
#[inline]
pub fn is_empty(&self) -> bool {
@ -93,6 +99,21 @@ impl FlowList {
}
}
impl Index<usize> for FlowList {
/// FIXME(pcwalton): O(n)!
type Output = Flow;
fn index(&self, index: usize) -> &Flow {
&**self.flows.iter().nth(index).unwrap()
}
}
impl IndexMut<usize> for FlowList {
/// FIXME(pcwalton): O(n)!
fn index_mut(&mut self, index: usize) -> &mut Flow {
self.iter_mut().nth(index).unwrap()
}
}
impl<'a> DoubleEndedIterator for MutFlowListIterator<'a> {
fn next_back(&mut self) -> Option<&'a mut Flow> {
self.it.next_back().map(flow_ref::deref_mut)