Skip to content

Commit 4e08907

Browse files
committed
Add safe rules for poll and select
1 parent 30e67a1 commit 4e08907

5 files changed

Lines changed: 1270 additions & 30 deletions

File tree

‎libcc2rs/src/fd.rs‎

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,26 @@ impl FdRegistry {
2727
raw
2828
}
2929

30+
fn lookup(&self, fd: i32) -> BorrowedFd<'_> {
31+
self.fds
32+
.get(fd as usize)
33+
.and_then(|slot| slot.as_ref())
34+
.unwrap_or_else(|| panic!("ub: bad fd {fd}"))
35+
.as_fd()
36+
}
37+
3038
pub fn with_fd<R>(fd: i32, f: impl FnOnce(BorrowedFd<'_>) -> R) -> R {
3139
FD_REGISTRY.with(|r| {
3240
let reg = r.borrow();
33-
let owned = reg
34-
.fds
35-
.get(fd as usize)
36-
.and_then(|slot| slot.as_ref())
37-
.unwrap_or_else(|| panic!("ub: bad fd {fd}"));
38-
f(owned.as_fd())
41+
f(reg.lookup(fd))
42+
})
43+
}
44+
45+
pub fn with_fds<R>(fds: &[i32], f: impl FnOnce(&[BorrowedFd<'_>]) -> R) -> R {
46+
FD_REGISTRY.with(|r| {
47+
let reg = r.borrow();
48+
let borrowed: Vec<BorrowedFd<'_>> = fds.iter().map(|&fd| reg.lookup(fd)).collect();
49+
f(&borrowed)
3950
})
4051
}
4152

‎rules/poll/tgt_refcount.rs‎

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,52 @@ use libcc2rs::*;
66
fn t1() -> libcc2rs::Pollfd {
77
Default::default()
88
}
9+
10+
fn f1(a0: Ptr<Pollfd>, a1: u64, a2: i32) -> i32 {
11+
let __p = a0.clone();
12+
let __timeout = match nix::poll::PollTimeout::try_from(a2) {
13+
Ok(__t) => __t,
14+
Err(_) => panic!("poll: unsupported timeout {}", a2),
15+
};
16+
let mut __idx = Vec::new();
17+
let mut __wanted = Vec::new();
18+
let mut __events = Vec::new();
19+
for __i in 0..(a1 as usize) {
20+
let (__fd, __ev) = __p
21+
.offset(__i)
22+
.with(|__e| (*__e.fd.borrow(), *__e.events.borrow()));
23+
__p.offset(__i)
24+
.with_mut(|__e| *__e.revents.borrow_mut() = 0);
25+
if __fd >= 0 {
26+
__idx.push(__i);
27+
__wanted.push(__fd);
28+
__events.push(__ev);
29+
}
30+
}
31+
FdRegistry::with_fds(&__wanted, |__b| {
32+
let mut __pfds: Vec<nix::poll::PollFd> = __b
33+
.iter()
34+
.zip(&__events)
35+
.map(|(&__fd, &__ev)| {
36+
nix::poll::PollFd::new(__fd, nix::poll::PollFlags::from_bits_truncate(__ev))
37+
})
38+
.collect();
39+
match nix::poll::poll(&mut __pfds, __timeout) {
40+
Ok(__count) => {
41+
for (__slot, &__i) in __pfds.iter().zip(&__idx) {
42+
let __rev = match __slot.revents() {
43+
Some(__r) => __r.bits(),
44+
None => 0,
45+
};
46+
__p.offset(__i)
47+
.with_mut(|__e| *__e.revents.borrow_mut() = __rev);
48+
}
49+
__count
50+
}
51+
Err(__e) => {
52+
libcc2rs::cpp2rust_errno().write(__e as i32);
53+
-1
54+
}
55+
}
56+
})
57+
}

‎rules/select/tgt_refcount.rs‎

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,109 @@ fn f4(a0: i32, a1: Ptr<CFdSet>) -> i32 {
2222
fn f5(a0: Ptr<CFdSet>) {
2323
a0.with_mut(|__s| __s.zero());
2424
}
25+
26+
fn f1(a0: i32, a1: Ptr<CFdSet>, a2: Ptr<CFdSet>, a3: Ptr<CFdSet>, a4: Ptr<Timeval>) -> i32 {
27+
let __rp = a1.clone();
28+
let __wp = a2.clone();
29+
let __ep = a3.clone();
30+
let __tp = a4.clone();
31+
let __r_fds: Vec<i32> = match __rp.is_null() {
32+
true => Vec::new(),
33+
false => __rp.with(|__s| (0..a0).filter(|&__fd| __s.isset(__fd)).collect()),
34+
};
35+
let __w_fds: Vec<i32> = match __wp.is_null() {
36+
true => Vec::new(),
37+
false => __wp.with(|__s| (0..a0).filter(|&__fd| __s.isset(__fd)).collect()),
38+
};
39+
let __e_fds: Vec<i32> = match __ep.is_null() {
40+
true => Vec::new(),
41+
false => __ep.with(|__s| (0..a0).filter(|&__fd| __s.isset(__fd)).collect()),
42+
};
43+
let mut __wanted = Vec::new();
44+
__wanted.extend(&__r_fds);
45+
__wanted.extend(&__w_fds);
46+
__wanted.extend(&__e_fds);
47+
FdRegistry::with_fds(&__wanted, |__b| {
48+
let __rn = __r_fds.len();
49+
let __wn = __w_fds.len();
50+
let mut __rs = nix::sys::select::FdSet::new();
51+
let mut __ws = nix::sys::select::FdSet::new();
52+
let mut __es = nix::sys::select::FdSet::new();
53+
for __bfd in &__b[..__rn] {
54+
__rs.insert(*__bfd);
55+
}
56+
for __bfd in &__b[__rn..__rn + __wn] {
57+
__ws.insert(*__bfd);
58+
}
59+
for __bfd in &__b[__rn + __wn..] {
60+
__es.insert(*__bfd);
61+
}
62+
let mut __tv = match __tp.is_null() {
63+
true => None,
64+
false => Some(__tp.with(|__t| {
65+
nix::sys::time::TimeVal::new(*__t.tv_sec.borrow() as _, *__t.tv_usec.borrow() as _)
66+
})),
67+
};
68+
match nix::sys::select::select(
69+
a0,
70+
match __rp.is_null() {
71+
true => None,
72+
false => Some(&mut __rs),
73+
},
74+
match __wp.is_null() {
75+
true => None,
76+
false => Some(&mut __ws),
77+
},
78+
match __ep.is_null() {
79+
true => None,
80+
false => Some(&mut __es),
81+
},
82+
__tv.as_mut(),
83+
) {
84+
Ok(__n) => {
85+
if !__rp.is_null() {
86+
__rp.with_mut(|__s| {
87+
__s.zero();
88+
for (__fd, __bfd) in __r_fds.iter().zip(&__b[..__rn]) {
89+
if __rs.contains(*__bfd) {
90+
__s.set(*__fd);
91+
}
92+
}
93+
});
94+
}
95+
if !__wp.is_null() {
96+
__wp.with_mut(|__s| {
97+
__s.zero();
98+
for (__fd, __bfd) in __w_fds.iter().zip(&__b[__rn..__rn + __wn]) {
99+
if __ws.contains(*__bfd) {
100+
__s.set(*__fd);
101+
}
102+
}
103+
});
104+
}
105+
if !__ep.is_null() {
106+
__ep.with_mut(|__s| {
107+
__s.zero();
108+
for (__fd, __bfd) in __e_fds.iter().zip(&__b[__rn + __wn..]) {
109+
if __es.contains(*__bfd) {
110+
__s.set(*__fd);
111+
}
112+
}
113+
});
114+
}
115+
match (__tp.is_null(), __tv.as_ref()) {
116+
(false, Some(__t)) => __tp.with_mut(|__dst| {
117+
*__dst.tv_sec.borrow_mut() = __t.tv_sec() as i64;
118+
*__dst.tv_usec.borrow_mut() = __t.tv_usec() as i64;
119+
}),
120+
_ => {}
121+
}
122+
__n
123+
}
124+
Err(__e) => {
125+
libcc2rs::cpp2rust_errno().write(__e as i32);
126+
-1
127+
}
128+
}
129+
})
130+
}

0 commit comments

Comments
 (0)