Skip to content

Commit

Permalink
Fix UB in Link and Link logic
Browse files Browse the repository at this point in the history
  • Loading branch information
uselessgoddess committed Jul 1, 2022
1 parent 2635c04 commit f7dfc0e
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 30 deletions.
34 changes: 16 additions & 18 deletions rust/doublets/src/data/link.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
use std::default::default;
use std::fmt::{Debug, Display, Formatter};
use std::ops::Index;
use std::slice::{from_raw_parts, SliceIndex};
use std::{
fmt,
fmt::{Debug, Formatter},
ops::Index,
slice::{from_raw_parts, SliceIndex},
};

use num_traits::zero;

use data::Query;
use data::ToQuery;
use data::{Query, ToQuery};
use num::LinkType;

#[derive(Default, Debug, Eq, PartialEq, Clone, Hash)]
#[derive(Default, Eq, PartialEq, Clone, Hash)]
#[repr(C)]
pub struct Link<T: LinkType> {
pub index: T,
pub source: T,
Expand All @@ -18,7 +20,7 @@ pub struct Link<T: LinkType> {

impl<T: LinkType> Link<T> {
pub fn nothing() -> Self {
default()
Self::default()
}

pub fn new(index: T, source: T, target: T) -> Self {
Expand All @@ -44,25 +46,21 @@ impl<T: LinkType> Link<T> {
pub fn is_partial(&self) -> bool {
self.index == self.source || self.index == self.target
}
}

impl<T: LinkType, I: SliceIndex<[T]>> Index<I> for Link<T> {
type Output = I::Output;

fn index(&self, index: I) -> &Self::Output {
let slice = unsafe { from_raw_parts(&self.index, 3) };
Index::index(slice, index)
pub fn as_slice(&self) -> &[T] {
// SAFETY: Link is repr(C) and therefore is safe to transmute to a slice
unsafe { from_raw_parts(&self.index, 3) }
}
}

impl<T: LinkType> Display for Link<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
impl<T: LinkType> Debug for Link<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "({}: {} {})", self.index, self.source, self.target)
}
}

impl<T: LinkType> ToQuery<T> for Link<T> {
fn to_query(&self) -> Query<'_, T> {
Query::new(unsafe { from_raw_parts(&self.index, 3) })
self.as_slice().to_query()
}
}
16 changes: 10 additions & 6 deletions rust/doublets/src/mem/split/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -810,12 +810,14 @@ impl<
query: &[T],
handler: WriteHandler<T>,
) -> Result<Flow, Box<dyn Error>> {
self.create_by_with(query, |before, after| handler(&before[..], &after[..]))
.map_err(|err| err.into())
self.create_by_with(query, |before, after| {
handler(before.as_slice(), after.as_slice())
})
.map_err(|err| err.into())
}

fn each_links(&self, query: &[T], handler: ReadHandler<T>) -> Result<Flow, Box<dyn Error>> {
Ok(self.each_by(query, |link| handler(&link[..])))
Ok(self.each_by(query, |link| handler(link.as_slice())))
}

fn update_links(
Expand All @@ -825,7 +827,7 @@ impl<
handler: WriteHandler<T>,
) -> Result<Flow, Box<dyn Error>> {
self.update_by_with(query, change, |before, after| {
handler(&before[..], &after[..])
handler(before.as_slice(), after.as_slice())
})
.map_err(|err| err.into())
}
Expand All @@ -835,8 +837,10 @@ impl<
query: &[T],
handler: WriteHandler<T>,
) -> Result<Flow, Box<dyn Error>> {
self.delete_by_with(query, |before, after| handler(&before[..], &after[..]))
.map_err(|err| err.into())
self.delete_by_with(query, |before, after| {
handler(before.as_slice(), after.as_slice())
})
.map_err(|err| err.into())
}
}

Expand Down
16 changes: 10 additions & 6 deletions rust/doublets/src/mem/unit/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -603,12 +603,14 @@ impl<T: LinkType, M: RawMem<LinkPart<T>>, TS: UnitTree<T>, TT: UnitTree<T>, TU:
query: &[T],
handler: WriteHandler<T>,
) -> Result<Flow, Box<dyn Error>> {
self.create_by_with(query, |before, after| handler(&before[..], &after[..]))
.map_err(|err| err.into())
self.create_by_with(query, |before, after| {
handler(before.as_slice(), after.as_slice())
})
.map_err(|err| err.into())
}

fn each_links(&self, query: &[T], handler: ReadHandler<T>) -> Result<Flow, Box<dyn Error>> {
Ok(self.each_by(query, |link| handler(&link[..])))
Ok(self.each_by(query, |link| handler(link.as_slice())))
}

fn update_links(
Expand All @@ -618,7 +620,7 @@ impl<T: LinkType, M: RawMem<LinkPart<T>>, TS: UnitTree<T>, TT: UnitTree<T>, TU:
handler: WriteHandler<T>,
) -> Result<Flow, Box<dyn Error>> {
self.update_by_with(query, change, |before, after| {
handler(&before[..], &after[..])
handler(before.as_slice(), after.as_slice())
})
.map_err(|err| err.into())
}
Expand All @@ -628,8 +630,10 @@ impl<T: LinkType, M: RawMem<LinkPart<T>>, TS: UnitTree<T>, TT: UnitTree<T>, TU:
query: &[T],
handler: WriteHandler<T>,
) -> Result<Flow, Box<dyn Error>> {
self.delete_by_with(query, |before, after| handler(&before[..], &after[..]))
.map_err(|err| err.into())
self.delete_by_with(query, |before, after| {
handler(before.as_slice(), after.as_slice())
})
.map_err(|err| err.into())
}
}

Expand Down
8 changes: 8 additions & 0 deletions rust/doublets/tests/link.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
use data::ToQuery;
use doublets::Link;

#[test]
fn link_to_query() {
let link = Link::<usize>::new(1, 2, 3);
assert_eq!([1, 2, 3], &link.to_query()[..]);
}

0 comments on commit f7dfc0e

Please sign in to comment.