-
Notifications
You must be signed in to change notification settings - Fork 13
/
build.rs
76 lines (63 loc) · 1.93 KB
/
build.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
use std::ptr;
#[allow(dead_code)]
struct Sample(usize);
trait SomeTrait {
fn call_me(&self) -> bool {
true
}
}
impl SomeTrait for Sample {}
fn layout_broken(what: &str) {
panic!(
concat!(
"Assumptions on layout are broken, this crate relies on ",
"`unsafe code guidelines` layout specification, ",
"now layout of {:?} is broken, report about it on github"
),
what
);
}
/// Tests some layout assumptions, these cases as of now:
///
/// 1. data pointer and vtable pointer location of trait objects
/// 2. data pointer and size location of slice objects
fn test_ptr_layouts() {
// Test for dyn object
{
#[repr(C)]
struct DynObj {
data_ptr: *const u8,
vtable: *const u8,
}
let sample = Box::new(Sample(100));
let data_ptr = Box::into_raw(sample);
let trait_obj: *const dyn SomeTrait = data_ptr;
let dyn_obj_repr: DynObj = unsafe { ptr::read(ptr::addr_of!(trait_obj) as *const DynObj) };
if dyn_obj_repr.data_ptr != data_ptr as *const u8 {
layout_broken("trait objects");
}
let out = unsafe { Box::from_raw(data_ptr) };
out.call_me();
}
// Test for slice object
{
let array = [1, 2, 3];
let slice: &[u8] = &array;
#[repr(C)]
struct Slice {
data_ptr: *const u8,
size: usize,
}
let slice_repr: Slice = unsafe { ptr::read(ptr::addr_of!(slice) as *const Slice) };
if slice_repr.data_ptr != slice.as_ptr() || slice_repr.size != slice.len() {
layout_broken("slices");
}
}
}
fn main() {
// NOTE: this will not protect from every possible case,
// for example, rust may add one more fat pointer type which this test
// will not check, host layout may be different from target layout,
// and probably more.
test_ptr_layouts();
}