-
Notifications
You must be signed in to change notification settings - Fork 52
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
miri: improve current situation #160
Comments
I'm 99.9% sure that the current crate is memory-safe. Unit tests, integration tests, at least a partial miri coverage. However, having miri on your side is a benefit, of course. |
I found a minimal reproducer for the miri issue. I also tried to solve it by giving all tags a use std::mem::size_of;
use std::ops::Deref;
use ptr_meta::Pointee;
#[repr(C, align(8))]
struct Align8<T>(T);
impl<T> Deref for Align8<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[derive(Debug, PartialEq, Eq)]
#[repr(u32)]
enum TagType {
Foo = 1,
Dst = 2,
}
#[repr(C)]
struct BaseTag {
typ: TagType,
size: u32,
}
// Tag type: 0x1
#[repr(C)]
struct FooTag {
base: BaseTag,
val: u64,
}
// Tag type: 0x2
#[derive(ptr_meta::Pointee)]
#[repr(C)]
struct DstTag {
base: BaseTag,
// embedded string slice
name: [u8],
}
impl DstTag {
fn name(&self) -> &str {
core::str::from_utf8(&self.name).unwrap()
}
}
fn cast_tag<'a, T: ?Sized + Pointee<Metadata = usize> + 'a>(tag: &'a BaseTag) -> &'a T {
let ptr = core::ptr::addr_of!(*tag);
unsafe { &*ptr_meta::from_raw_parts(ptr.cast(), tag.size as usize - size_of::<BaseTag>()) }
}
mod tests {
use super::*;
#[test]
fn test_parse_tag() {
let bytes = Align8([
// <begin of tag foo>
TagType::Foo as u32 as u8, // tag foo: type
0x0,
0x0,
0x0,
16, // tag foo: size
0x0,
0x0,
0x0,
0x37, // tag foo: val
0x13,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
// <end of tag foo>
// <begin of tag dst>
TagType::Dst as u32 as u8, // tag dst: type
0x0,
0x0,
0x0,
16, // tag dst: size
0x0,
0x0,
0x0,
b'h',
b'e',
b'l',
b'l',
b'o',
b' ',
b'!',
b'\0', // tag foo: name
// <end of tag dst>
]);
// Parsing of Tag Foo
let base_tag_ptr = bytes.as_ptr().cast::<BaseTag>();
let base_tag_ref = unsafe { &*base_tag_ptr };
assert_eq!(base_tag_ref.size, 16);
assert_eq!(base_tag_ref.typ, TagType::Foo);
let tag_foo = unsafe { &*base_tag_ptr.cast::<FooTag>() };
assert_eq!(tag_foo.val, 0x1337);
// Parsing of Tag Dst
let base_tag_ptr = unsafe {
bytes
.as_ptr()
.add(tag_foo.base.size as usize)
.cast::<BaseTag>()
};
let base_tag_ref = unsafe { &*base_tag_ptr };
assert_eq!(base_tag_ref.typ, TagType::Dst);
assert_eq!(base_tag_ref.size, 16);
let tag_dst = cast_tag::<DstTag>(base_tag_ref);
assert_eq!(tag_dst.name(), "hello !\0");
}
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
In #128, I added basic miri support. Due to the following issues, miri can't embrace all it's funcitionality:
cast_tag
(transitively) fails, as miri can't guarantee that the memory is valid, unfortunatelystruct_as_bytes() ... cast
is done, there are alignment issues as the returned Vec is of course only aligned to a one byte boundary... so far, in tests this never was a problem, luckily. At least on x86.The text was updated successfully, but these errors were encountered: