-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy path0075-shine-stdext.rs
159 lines (129 loc) · 4.56 KB
/
0075-shine-stdext.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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/*!
```rudra-poc
[target]
crate = "shine-stdext"
version = "0.2.0"
[[target.peer]]
crate = "crossbeam-utils"
version = "0.8.0"
[test]
cargo_toolchain = "nightly"
[report]
issue_url = "https://github.com/gzp-crey/shine_deprecated/issues/1"
issue_date = 2020-12-23
[[bugs]]
analyzer = "SendSyncVariance"
bug_class = "SendSyncVariance"
bug_count = 5
rudra_report_locations = [
"src/namedstore.rs:131:1: 131:42",
"src/namedstore.rs:133:1: 133:42",
"src/unnamedstore.rs:93:1: 93:36",
"src/unnamedstore.rs:94:1: 94:36",
"src/spscstate.rs:25:1: 25:43",
]
[[bugs]]
analyzer = "Manual"
guide = "SendSyncVariance"
bug_class = "Other"
rudra_report_locations = []
```
!*/
#![forbid(unsafe_code)]
use shine_stdext::unnamedstore::Store;
use crossbeam_utils::thread;
use std::cell::Cell;
// A simple tagged union used to demonstrate problems with data-races.
#[derive(Debug, Clone, Copy)]
enum RefOrInt {
Ref(&'static u64),
Int(u128),
}
static STATIC_INT: u64 = 123;
// 1. Store<D> implements Send/Sync for all D.
fn wild_send_sync_unnamed_store() {
let cell = Cell::new(RefOrInt::Ref(&STATIC_INT));
let store = Store::<&Cell<RefOrInt>>::new();
let idx = store.try_write().unwrap().add(&cell);
thread::scope(|s| {
s.spawn(|_| {
let read_guard = store.try_read().unwrap();
let smuggled_cell = read_guard.at(&idx);
loop {
// Repeatedly write Ref(&addr) and Int(0xdeadbeef) into the cell.
smuggled_cell.set(RefOrInt::Ref(&STATIC_INT));
smuggled_cell.set(RefOrInt::Int(0xdeadbeef));
}
});
loop {
if let RefOrInt::Ref(addr) = cell.get() {
// Hope that between the time we pattern match the object as a
// `Ref`, it gets written to by the other thread.
if addr as *const u64 == &STATIC_INT as *const u64 {
continue;
}
println!("Pointer is now: {:p}", addr);
println!("Dereferencing addr will now segfault: {}", *addr);
}
}
});
}
use shine_stdext::spscstate::state_channel;
// Needed because state_channel requires the type to implement Default.
#[derive(Debug, Clone)]
struct RefOrIntCellContainer(Cell<RefOrInt>);
impl Default for RefOrIntCellContainer {
fn default() -> Self {
Self(Cell::new(RefOrInt::Ref(&STATIC_INT)))
}
}
// 2. shine_stdext::spscstate::RefSendBuffer automatically implements Send and
// Sync but allows access to non-Send/Sync types.
fn wild_send_sync_state_channel() {
let cell_container = RefOrIntCellContainer(Cell::new(RefOrInt::Ref(&STATIC_INT)));
let (sender, receiver) = state_channel::<RefOrIntCellContainer>();
let send_buffer = sender.send_buffer().unwrap();
thread::scope(|s| {
s.spawn(|_| {
let smuggled_cell = &send_buffer.0;
loop {
// Repeatedly write Ref(&addr) and Int(0xdeadbeef) into the cell.
smuggled_cell.set(RefOrInt::Ref(&STATIC_INT));
smuggled_cell.set(RefOrInt::Int(0xdeadbeef));
}
});
loop {
if let RefOrInt::Ref(addr) = send_buffer.0.get() {
// Hope that between the time we pattern match the object as a
// `Ref`, it gets written to by the other thread.
if addr as *const u64 == &STATIC_INT as *const u64 {
continue;
}
println!("Pointer is now: {:p}", addr);
println!("Dereferencing addr will now segfault: {}", *addr);
}
}
});
}
// 3. Index does not track which Store it came from allowing for aliasing
// violations when used across multiple stores.
fn index_aliasing_violation() {
let store = Store::<RefOrInt>::new();
let another_store = Store::<RefOrInt>::new();
let idx = store.try_write().unwrap().add(RefOrInt::Ref(&42));
let mut write_guard_1 = store.try_write().unwrap();
let mut write_guard_2 = another_store.try_write().unwrap();
let mutable_ref_one = write_guard_1.at_mut(&idx);
let mutable_ref_two = write_guard_2.at_mut(&idx);
println!("Pointer points to: {:?}", mutable_ref_one);
if let RefOrInt::Ref(ref addr) = mutable_ref_one {
*mutable_ref_two = RefOrInt::Int(0xdeadbeef);
println!("Pointer now points to: {:p}", *addr);
println!("Dereferencing addr will now segfault: {}", **addr);
}
}
fn main() {
//wild_send_sync_unnamed_store();
//wild_send_sync_state_channel();
index_aliasing_violation();
}