Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions libcc2rs/src/libc_shims/dirent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,21 @@ impl Default for Dirent {
}
}

impl Dirent {
pub fn from_entry(ino: u64, name: &[u8], d_type: u8) -> Self {
let de = Dirent::default();
*de.d_ino.borrow_mut() = ino;
*de.d_type.borrow_mut() = d_type;
{
let mut nm = de.d_name.borrow_mut();
let n = name.len().min(nm.len() - 1);
nm[..n].copy_from_slice(&name[..n]);
nm[n] = 0;
}
de
}
}

impl Clone for Dirent {
fn clone(&self) -> Self {
Self {
Expand All @@ -44,6 +59,29 @@ pub struct CDir {
pub pos: Cell<usize>,
}

impl CDir {
pub fn from_dir(dir: nix::dir::Dir) -> Self {
let mut entries: Vec<(u64, Vec<u8>, u8)> = Vec::new();
for ent in dir.into_iter().flatten() {
let ty = match ent.file_type() {
Some(nix::dir::Type::Fifo) => ::libc::DT_FIFO,
Some(nix::dir::Type::CharacterDevice) => ::libc::DT_CHR,
Some(nix::dir::Type::Directory) => ::libc::DT_DIR,
Some(nix::dir::Type::BlockDevice) => ::libc::DT_BLK,
Some(nix::dir::Type::File) => ::libc::DT_REG,
Some(nix::dir::Type::Symlink) => ::libc::DT_LNK,
Some(nix::dir::Type::Socket) => ::libc::DT_SOCK,
None => ::libc::DT_UNKNOWN,
};
entries.push((ent.ino(), ent.file_name().to_bytes().to_vec(), ty));
}
Self {
entries,
pos: Cell::new(0),
}
}
}

impl ByteRepr for CDir {}

impl ByteRepr for ::libc::dirent {}
19 changes: 19 additions & 0 deletions libcc2rs/src/libc_shims/pwd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,25 @@ pub struct Passwd {
pub pw_shell: Value<Ptr<u8>>,
}

impl Passwd {
pub fn from_user(u: &nix::unistd::User) -> Self {
let mk = |s: &[u8]| -> Value<Ptr<u8>> {
let mut v = s.to_vec();
v.push(0);
Rc::new(RefCell::new(Ptr::alloc_array(v.into_boxed_slice())))
};
Self {
pw_name: mk(u.name.as_bytes()),
pw_passwd: mk(u.passwd.as_bytes()),
pw_uid: Rc::new(RefCell::new(u.uid.as_raw())),
pw_gid: Rc::new(RefCell::new(u.gid.as_raw())),
pw_gecos: mk(u.gecos.as_bytes()),
pw_dir: mk(u.dir.as_os_str().as_encoded_bytes()),
pw_shell: mk(u.shell.as_os_str().as_encoded_bytes()),
}
}
}

impl Clone for Passwd {
fn clone(&self) -> Self {
Self {
Expand Down
21 changes: 21 additions & 0 deletions libcc2rs/src/libc_shims/stat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,27 @@ pub struct Stat {
pub st_ctime: Value<i64>,
}

impl Stat {
#[allow(clippy::unnecessary_cast)]
pub fn from_libc(s: &::libc::stat) -> Self {
Self {
st_dev: Rc::new(RefCell::new(s.st_dev as u64)),
st_ino: Rc::new(RefCell::new(s.st_ino as u64)),
st_nlink: Rc::new(RefCell::new(s.st_nlink as u64)),
st_mode: Rc::new(RefCell::new(s.st_mode as u32)),
st_uid: Rc::new(RefCell::new(s.st_uid)),
st_gid: Rc::new(RefCell::new(s.st_gid)),
st_rdev: Rc::new(RefCell::new(s.st_rdev as u64)),
st_size: Rc::new(RefCell::new(s.st_size as i64)),
st_blksize: Rc::new(RefCell::new(s.st_blksize as i64)),
st_blocks: Rc::new(RefCell::new(s.st_blocks as i64)),
st_atime: Rc::new(RefCell::new(s.st_atime as i64)),
st_mtime: Rc::new(RefCell::new(s.st_mtime as i64)),
st_ctime: Rc::new(RefCell::new(s.st_ctime as i64)),
}
}
}

impl Clone for Stat {
fn clone(&self) -> Self {
Self {
Expand Down
11 changes: 11 additions & 0 deletions rules/cstdlib/tgt_refcount.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,17 @@ fn f5(a0: usize, a1: usize) -> AnyPtr {
libcc2rs::calloc_refcount(a0, a1)
}

fn f6(a0: Ptr<u8>) -> Ptr<u8> {
match ::std::env::var(a0.to_rust_string()) {
Ok(__val) => {
let mut __bytes = __val.into_bytes();
__bytes.push(0);
Ptr::alloc_array(__bytes.into_boxed_slice())
}
Err(_) => Ptr::null(),
}
}

fn f8(a0: AnyPtr, a1: AnyPtr, a2: usize, a3: usize, a4: fn(AnyPtr, AnyPtr) -> i32) -> AnyPtr {
let __base = a1.reinterpret_cast::<u8>();
let mut __lo: isize = 0;
Expand Down
32 changes: 32 additions & 0 deletions rules/dirent/tgt_refcount.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,35 @@ fn t1() -> Ptr<libcc2rs::CDir> {
fn t2() -> libcc2rs::Dirent {
Default::default()
}

fn f1(a0: Ptr<u8>) -> Ptr<CDir> {
match nix::dir::Dir::open(
a0.to_rust_string().as_str(),
nix::fcntl::OFlag::O_RDONLY,
nix::sys::stat::Mode::empty(),
) {
Ok(__dir) => Ptr::alloc(CDir::from_dir(__dir)),
Err(__e) => {
libcc2rs::cpp2rust_errno().write(__e as i32);
Ptr::null()
}
}
}

fn f2(a0: Ptr<CDir>) -> Ptr<Dirent> {
a0.with(|__d| {
let __i = __d.pos.get();
if __i >= __d.entries.len() {
Ptr::null()
} else {
__d.pos.set(__i + 1);
let __e = &__d.entries[__i];
Ptr::alloc(Dirent::from_entry(__e.0, &__e.1, __e.2))
}
})
}

fn f3(a0: Ptr<CDir>) -> i32 {
a0.delete();
0
}
12 changes: 12 additions & 0 deletions rules/locale/tgt_refcount.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright (c) 2022-present INESC-ID.
// Distributed under the MIT license that can be found in the LICENSE file.

use libcc2rs::*;

// Rust does not have support for localization.
//
// TODO: we need to track ourselves the locale settings and change the behavior of the relevant
// functions based on the set locale.
fn f1(a0: i32, a1: Ptr<u8>) -> Ptr<u8> {
Ptr::from_string_literal(b"C")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is not correct for sure :)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rust does not seem to have support for localization

The man page of setlocale says:

       A successful call to setlocale() returns an opaque string that
       corresponds to the locale set.  This string may be allocated in
       static storage.  The string returned is such that a subsequent
       call with that string and its associated category will restore
       that part of the process's locale.  The return value is NULL if
       the request cannot be honored.

So the real options here are to return C (The locale "C" or "POSIX" is a portable locale; it exists on all conforming systems.) or NULL. NULL looks more like a failure, so I chose "C" instead.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably need to track the locale ourselves and change the behavior of relevant string functions then

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a TODO about that

}
11 changes: 11 additions & 0 deletions rules/pwd/tgt_refcount.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,14 @@ use libcc2rs::*;
fn t1() -> libcc2rs::Passwd {
Default::default()
}

fn f1(a0: u32) -> Ptr<Passwd> {
match nix::unistd::User::from_uid(nix::unistd::Uid::from_raw(a0)) {
Ok(Some(__u)) => Ptr::alloc(Passwd::from_user(&__u)),
Ok(None) => Ptr::null(),
Err(__e) => {
libcc2rs::cpp2rust_errno().write(__e as i32);
Ptr::null()
}
}
}
2 changes: 2 additions & 0 deletions rules/src/modules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ pub mod ip_tgt_refcount;
pub mod ip_tgt_unsafe;
#[path = r#"../limits/tgt_unsafe.rs"#]
pub mod limits_tgt_unsafe;
#[path = r#"../locale/tgt_refcount.rs"#]
pub mod locale_tgt_refcount;
#[path = r#"../locale/tgt_unsafe.rs"#]
pub mod locale_tgt_unsafe;
#[path = r#"../map/tgt_refcount.rs"#]
Expand Down
26 changes: 26 additions & 0 deletions rules/stat/tgt_refcount.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,29 @@ use libcc2rs::*;
fn t1() -> libcc2rs::Stat {
Default::default()
}

fn f1(a0: Ptr<u8>, a1: Ptr<Stat>) -> i32 {
match nix::sys::stat::stat(a0.to_rust_string().as_str()) {
Ok(__s) => {
a1.with_mut(|__st| *__st = Stat::from_libc(&__s));
0
}
Err(__e) => {
libcc2rs::cpp2rust_errno().write(__e as i32);
-1
}
}
}

fn f3(a0: Ptr<u8>, a1: ::libc::mode_t) -> i32 {
match nix::unistd::mkdir(
a0.to_rust_string().as_str(),
nix::sys::stat::Mode::from_bits_truncate(a1),
) {
Ok(()) => 0,
Err(__e) => {
libcc2rs::cpp2rust_errno().write(__e as i32);
-1
}
}
}
1 change: 0 additions & 1 deletion tests/unit/libc_char_ptr_field.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// no-compile: refcount
#include <dirent.h>
#include <pwd.h>
#include <unistd.h>
Expand Down
58 changes: 58 additions & 0 deletions tests/unit/out/refcount/libc_char_ptr_field.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
extern crate libcc2rs;
use libcc2rs::*;
use std::cell::RefCell;
use std::collections::BTreeMap;
use std::io::prelude::*;
use std::io::{Read, Seek, Write};
use std::os::fd::AsFd;
use std::rc::{Rc, Weak};
pub fn main() {
std::process::exit(main_0());
}
fn main_0() -> i32 {
let pw: Value<Ptr<libcc2rs::Passwd>> = Rc::new(RefCell::new(
match nix::unistd::User::from_uid(nix::unistd::Uid::from_raw(
nix::unistd::geteuid().as_raw(),
)) {
Ok(Some(__u)) => Ptr::alloc(Passwd::from_user(&__u)),
Ok(None) => Ptr::null(),
Err(__e) => {
libcc2rs::cpp2rust_errno().write(__e as i32);
Ptr::null()
}
},
));
if !!(*pw.borrow()).is_null() {
return 0;
}
let home: Value<Ptr<u8>> = Rc::new(RefCell::new(
(*(*(*pw.borrow()).upgrade().deref()).pw_dir.borrow()).clone(),
));
let d: Value<Ptr<libcc2rs::Dirent>> = Rc::new(RefCell::new(
match nix::dir::Dir::open(
Ptr::from_string_literal(b"/tmp").to_rust_string().as_str(),
nix::fcntl::OFlag::O_RDONLY,
nix::sys::stat::Mode::empty(),
) {
Ok(__dir) => Ptr::alloc(CDir::from_dir(__dir)),
Err(__e) => {
libcc2rs::cpp2rust_errno().write(__e as i32);
Ptr::null()
}
}
.with(|__d| {
let __i = __d.pos.get();
if __i >= __d.entries.len() {
Ptr::null()
} else {
__d.pos.set(__i + 1);
let __e = &__d.entries[__i];
Ptr::alloc(Dirent::from_entry(__e.0, &__e.1, __e.2))
}
}),
));
let dname: Value<Ptr<u8>> = Rc::new(RefCell::new(
((*(*d.borrow()).upgrade().deref()).d_name.as_pointer() as Ptr<u8>),
));
return 0;
}
Loading