Skip to content

Commit 5ed6982

Browse files
authored
Add misc safe rules (#264)
1 parent adab7fe commit 5ed6982

11 files changed

Lines changed: 230 additions & 1 deletion

File tree

‎libcc2rs/src/libc_shims/dirent.rs‎

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,21 @@ impl Default for Dirent {
2525
}
2626
}
2727

28+
impl Dirent {
29+
pub fn from_entry(ino: u64, name: &[u8], d_type: u8) -> Self {
30+
let de = Dirent::default();
31+
*de.d_ino.borrow_mut() = ino;
32+
*de.d_type.borrow_mut() = d_type;
33+
{
34+
let mut nm = de.d_name.borrow_mut();
35+
let n = name.len().min(nm.len() - 1);
36+
nm[..n].copy_from_slice(&name[..n]);
37+
nm[n] = 0;
38+
}
39+
de
40+
}
41+
}
42+
2843
impl Clone for Dirent {
2944
fn clone(&self) -> Self {
3045
Self {
@@ -44,6 +59,29 @@ pub struct CDir {
4459
pub pos: Cell<usize>,
4560
}
4661

62+
impl CDir {
63+
pub fn from_dir(dir: nix::dir::Dir) -> Self {
64+
let mut entries: Vec<(u64, Vec<u8>, u8)> = Vec::new();
65+
for ent in dir.into_iter().flatten() {
66+
let ty = match ent.file_type() {
67+
Some(nix::dir::Type::Fifo) => ::libc::DT_FIFO,
68+
Some(nix::dir::Type::CharacterDevice) => ::libc::DT_CHR,
69+
Some(nix::dir::Type::Directory) => ::libc::DT_DIR,
70+
Some(nix::dir::Type::BlockDevice) => ::libc::DT_BLK,
71+
Some(nix::dir::Type::File) => ::libc::DT_REG,
72+
Some(nix::dir::Type::Symlink) => ::libc::DT_LNK,
73+
Some(nix::dir::Type::Socket) => ::libc::DT_SOCK,
74+
None => ::libc::DT_UNKNOWN,
75+
};
76+
entries.push((ent.ino(), ent.file_name().to_bytes().to_vec(), ty));
77+
}
78+
Self {
79+
entries,
80+
pos: Cell::new(0),
81+
}
82+
}
83+
}
84+
4785
impl ByteRepr for CDir {}
4886

4987
impl ByteRepr for ::libc::dirent {}

‎libcc2rs/src/libc_shims/pwd.rs‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,25 @@ pub struct Passwd {
1616
pub pw_shell: Value<Ptr<u8>>,
1717
}
1818

19+
impl Passwd {
20+
pub fn from_user(u: &nix::unistd::User) -> Self {
21+
let mk = |s: &[u8]| -> Value<Ptr<u8>> {
22+
let mut v = s.to_vec();
23+
v.push(0);
24+
Rc::new(RefCell::new(Ptr::alloc_array(v.into_boxed_slice())))
25+
};
26+
Self {
27+
pw_name: mk(u.name.as_bytes()),
28+
pw_passwd: mk(u.passwd.as_bytes()),
29+
pw_uid: Rc::new(RefCell::new(u.uid.as_raw())),
30+
pw_gid: Rc::new(RefCell::new(u.gid.as_raw())),
31+
pw_gecos: mk(u.gecos.as_bytes()),
32+
pw_dir: mk(u.dir.as_os_str().as_encoded_bytes()),
33+
pw_shell: mk(u.shell.as_os_str().as_encoded_bytes()),
34+
}
35+
}
36+
}
37+
1938
impl Clone for Passwd {
2039
fn clone(&self) -> Self {
2140
Self {

‎libcc2rs/src/libc_shims/stat.rs‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,27 @@ pub struct Stat {
2222
pub st_ctime: Value<i64>,
2323
}
2424

25+
impl Stat {
26+
#[allow(clippy::unnecessary_cast)]
27+
pub fn from_libc(s: &::libc::stat) -> Self {
28+
Self {
29+
st_dev: Rc::new(RefCell::new(s.st_dev as u64)),
30+
st_ino: Rc::new(RefCell::new(s.st_ino as u64)),
31+
st_nlink: Rc::new(RefCell::new(s.st_nlink as u64)),
32+
st_mode: Rc::new(RefCell::new(s.st_mode as u32)),
33+
st_uid: Rc::new(RefCell::new(s.st_uid)),
34+
st_gid: Rc::new(RefCell::new(s.st_gid)),
35+
st_rdev: Rc::new(RefCell::new(s.st_rdev as u64)),
36+
st_size: Rc::new(RefCell::new(s.st_size as i64)),
37+
st_blksize: Rc::new(RefCell::new(s.st_blksize as i64)),
38+
st_blocks: Rc::new(RefCell::new(s.st_blocks as i64)),
39+
st_atime: Rc::new(RefCell::new(s.st_atime as i64)),
40+
st_mtime: Rc::new(RefCell::new(s.st_mtime as i64)),
41+
st_ctime: Rc::new(RefCell::new(s.st_ctime as i64)),
42+
}
43+
}
44+
}
45+
2546
impl Clone for Stat {
2647
fn clone(&self) -> Self {
2748
Self {

‎rules/cstdlib/tgt_refcount.rs‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,17 @@ fn f5(a0: usize, a1: usize) -> AnyPtr {
1919
libcc2rs::calloc_refcount(a0, a1)
2020
}
2121

22+
fn f6(a0: Ptr<u8>) -> Ptr<u8> {
23+
match ::std::env::var(a0.to_rust_string()) {
24+
Ok(__val) => {
25+
let mut __bytes = __val.into_bytes();
26+
__bytes.push(0);
27+
Ptr::alloc_array(__bytes.into_boxed_slice())
28+
}
29+
Err(_) => Ptr::null(),
30+
}
31+
}
32+
2233
fn f8(a0: AnyPtr, a1: AnyPtr, a2: usize, a3: usize, a4: fn(AnyPtr, AnyPtr) -> i32) -> AnyPtr {
2334
let __base = a1.reinterpret_cast::<u8>();
2435
let mut __lo: isize = 0;

‎rules/dirent/tgt_refcount.rs‎

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,35 @@ fn t1() -> Ptr<libcc2rs::CDir> {
1010
fn t2() -> libcc2rs::Dirent {
1111
Default::default()
1212
}
13+
14+
fn f1(a0: Ptr<u8>) -> Ptr<CDir> {
15+
match nix::dir::Dir::open(
16+
a0.to_rust_string().as_str(),
17+
nix::fcntl::OFlag::O_RDONLY,
18+
nix::sys::stat::Mode::empty(),
19+
) {
20+
Ok(__dir) => Ptr::alloc(CDir::from_dir(__dir)),
21+
Err(__e) => {
22+
libcc2rs::cpp2rust_errno().write(__e as i32);
23+
Ptr::null()
24+
}
25+
}
26+
}
27+
28+
fn f2(a0: Ptr<CDir>) -> Ptr<Dirent> {
29+
a0.with(|__d| {
30+
let __i = __d.pos.get();
31+
if __i >= __d.entries.len() {
32+
Ptr::null()
33+
} else {
34+
__d.pos.set(__i + 1);
35+
let __e = &__d.entries[__i];
36+
Ptr::alloc(Dirent::from_entry(__e.0, &__e.1, __e.2))
37+
}
38+
})
39+
}
40+
41+
fn f3(a0: Ptr<CDir>) -> i32 {
42+
a0.delete();
43+
0
44+
}

‎rules/locale/tgt_refcount.rs‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Copyright (c) 2022-present INESC-ID.
2+
// Distributed under the MIT license that can be found in the LICENSE file.
3+
4+
use libcc2rs::*;
5+
6+
// Rust does not have support for localization.
7+
//
8+
// TODO: we need to track ourselves the locale settings and change the behavior of the relevant
9+
// functions based on the set locale.
10+
fn f1(a0: i32, a1: Ptr<u8>) -> Ptr<u8> {
11+
Ptr::from_string_literal(b"C")
12+
}

‎rules/pwd/tgt_refcount.rs‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,14 @@ use libcc2rs::*;
66
fn t1() -> libcc2rs::Passwd {
77
Default::default()
88
}
9+
10+
fn f1(a0: u32) -> Ptr<Passwd> {
11+
match nix::unistd::User::from_uid(nix::unistd::Uid::from_raw(a0)) {
12+
Ok(Some(__u)) => Ptr::alloc(Passwd::from_user(&__u)),
13+
Ok(None) => Ptr::null(),
14+
Err(__e) => {
15+
libcc2rs::cpp2rust_errno().write(__e as i32);
16+
Ptr::null()
17+
}
18+
}
19+
}

‎rules/src/modules.rs‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ pub mod ip_tgt_refcount;
8484
pub mod ip_tgt_unsafe;
8585
#[path = r#"../limits/tgt_unsafe.rs"#]
8686
pub mod limits_tgt_unsafe;
87+
#[path = r#"../locale/tgt_refcount.rs"#]
88+
pub mod locale_tgt_refcount;
8789
#[path = r#"../locale/tgt_unsafe.rs"#]
8890
pub mod locale_tgt_unsafe;
8991
#[path = r#"../map/tgt_refcount.rs"#]

‎rules/stat/tgt_refcount.rs‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,29 @@ use libcc2rs::*;
66
fn t1() -> libcc2rs::Stat {
77
Default::default()
88
}
9+
10+
fn f1(a0: Ptr<u8>, a1: Ptr<Stat>) -> i32 {
11+
match nix::sys::stat::stat(a0.to_rust_string().as_str()) {
12+
Ok(__s) => {
13+
a1.with_mut(|__st| *__st = Stat::from_libc(&__s));
14+
0
15+
}
16+
Err(__e) => {
17+
libcc2rs::cpp2rust_errno().write(__e as i32);
18+
-1
19+
}
20+
}
21+
}
22+
23+
fn f3(a0: Ptr<u8>, a1: ::libc::mode_t) -> i32 {
24+
match nix::unistd::mkdir(
25+
a0.to_rust_string().as_str(),
26+
nix::sys::stat::Mode::from_bits_truncate(a1),
27+
) {
28+
Ok(()) => 0,
29+
Err(__e) => {
30+
libcc2rs::cpp2rust_errno().write(__e as i32);
31+
-1
32+
}
33+
}
34+
}

‎tests/unit/libc_char_ptr_field.c‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
// no-compile: refcount
21
#include <dirent.h>
32
#include <pwd.h>
43
#include <unistd.h>

0 commit comments

Comments
 (0)