Reputation: 1632
Lets say we have an OS of single address space. To maintain stability we need to force memory protection for user applications, e.g. to forbid usage of 'unsafe' keyword unless user has a special capability.
Our users need to have a way to safely read/write arbitrary structures from/to byte streams (e.g. files). Of course we are talking about structures which don't contain references (otherwise we loose memory safety).
Now I tried to implement this kind of generic reader function:
#![feature(core)]
use std::io;
use std::mem;
use std::raw;
fn read<T>(reader: &mut io::Read, dest: &mut T) -> io::Result<usize> {
let slice = raw::Slice{ data:dest, len:mem::size_of::<T>() };
let buf: &mut [u8] = unsafe { mem::transmute(slice) };
reader.read(buf)
}
The implementation above has a serious problem. It allows to read structures which contain references. So how can I fix that?
Upvotes: 3
Views: 413
Reputation: 31203
You can use a so-called "Marker Trait": a custom unsafe trait with a default impl for all types and a negative trait impl for all references. Since you forbid all uses of unsafe
, the user cannot implement the trait on their own, and therefore there cannot be an implementation of the trait for any type that has references.
You should probably also include raw pointers (*mut
and *const
) in the negative impls... otherwise the user could deserialize a Vec
or some other "safe" type that has inner unsafety.
#![feature(optin_builtin_traits)]
unsafe trait NoInnerRefs {}
impl<'a, T> !NoInnerRefs for &'a T {}
unsafe impl NoInnerRefs for .. {}
struct A(&'static str);
struct B(i32);
fn test<T: NoInnerRefs>(_: T) {
}
fn main() {
test(B(5));
test(A("hi"));
}
This will fail to compile:
<anon>:17:5: 17:9 error: the trait `NoInnerRefs` is not implemented for the type `&'static str` [E0277]
<anon>:17 test(A("hi"));
^~~~
Upvotes: 5