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
4 changes: 3 additions & 1 deletion cpp2rust/converter/converter_lib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -687,7 +687,9 @@ static void GetAllVarsImpl(const clang::Stmt *stmt,
}

if (auto *decl_ref = clang::dyn_cast<clang::DeclRefExpr>(stmt)) {
vars.insert(decl_ref->getDecl());
if (!clang::isa<clang::EnumConstantDecl>(decl_ref->getDecl())) {
vars.insert(decl_ref->getDecl());
}
} else if (auto *member = clang::dyn_cast<clang::MemberExpr>(stmt)) {
vars.insert(member->getMemberDecl());
GetAllVarsImpl(member->getBase(), vars);
Expand Down
37 changes: 36 additions & 1 deletion libcc2rs/src/libc_shims/ifaddrs.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) 2022-present INESC-ID.
// Distributed under the MIT license that can be found in the LICENSE file.

use super::Sockaddr;
use super::{Sockaddr, SockaddrIn, SockaddrIn6, SockaddrStorage};
use crate::{ByteRepr, Ptr, Value};
use std::cell::RefCell;
use std::rc::Rc;
Expand All @@ -15,6 +15,41 @@ pub struct Ifaddrs {
pub ifa_netmask: Value<Ptr<Sockaddr>>,
}

impl Ifaddrs {
pub fn from_interface_address(ifa: &nix::ifaddrs::InterfaceAddress) -> Self {
fn mk_addr(ss: Option<&nix::sys::socket::SockaddrStorage>) -> Ptr<Sockaddr> {
match ss {
None => Ptr::null(),
Some(a) => match (a.as_sockaddr_in(), a.as_sockaddr_in6()) {
(Some(v4), _) => {
let l = ::libc::sockaddr_in::from(*v4);
let st = Ptr::alloc(SockaddrStorage::default());
st.reinterpret_cast::<SockaddrIn>()
.write(SockaddrIn::from_libc(&l));
st.reinterpret_cast::<Sockaddr>()
}
(None, Some(v6)) => {
let l = ::libc::sockaddr_in6::from(*v6);
let st = Ptr::alloc(SockaddrStorage::default());
st.reinterpret_cast::<SockaddrIn6>()
.write(SockaddrIn6::from_libc(&l));
st.reinterpret_cast::<Sockaddr>()
}
(None, None) => Ptr::null(),
},
}
}
let node = Ifaddrs::default();
let mut name = ifa.interface_name.clone().into_bytes();
name.push(0);
*node.ifa_name.borrow_mut() = Ptr::alloc_array(name.into_boxed_slice());
*node.ifa_flags.borrow_mut() = ifa.flags.bits() as u32;
*node.ifa_addr.borrow_mut() = mk_addr(ifa.address.as_ref());
*node.ifa_netmask.borrow_mut() = mk_addr(ifa.netmask.as_ref());
node
}
}

impl Clone for Ifaddrs {
fn clone(&self) -> Self {
Self {
Expand Down
84 changes: 84 additions & 0 deletions libcc2rs/src/libc_shims/socket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,90 @@ pub struct SockaddrStorage {
pub __pad: Value<Box<[u8]>>,
}

impl SockaddrIn {
#[allow(clippy::unnecessary_cast)]
pub fn from_libc(l: &::libc::sockaddr_in) -> Self {
Self {
sin_family: Rc::new(RefCell::new(l.sin_family as u16)),
sin_port: Rc::new(RefCell::new(l.sin_port)),
sin_addr: Rc::new(RefCell::new(InAddr {
s_addr: Rc::new(RefCell::new(l.sin_addr.s_addr)),
})),
sin_zero: Rc::new(RefCell::new(
l.sin_zero
.iter()
.map(|&b| b as u8)
.collect::<Vec<u8>>()
.into_boxed_slice(),
)),
}
}

pub fn from_ipv4(addr: &::std::net::Ipv4Addr, port: u16) -> Self {
let s = Self::default();
*s.sin_family.borrow_mut() = ::libc::AF_INET as u16;
*s.sin_port.borrow_mut() = port.to_be();
*s.sin_addr.borrow().s_addr.borrow_mut() = u32::from(*addr).to_be();
s
}

#[cfg(target_os = "linux")]
pub fn to_libc(&self) -> ::libc::sockaddr_in {
let mut sin_zero = [0u8; 8];
sin_zero.copy_from_slice(&self.sin_zero.borrow());
::libc::sockaddr_in {
sin_family: *self.sin_family.borrow(),
sin_port: *self.sin_port.borrow(),
sin_addr: ::libc::in_addr {
s_addr: *self.sin_addr.borrow().s_addr.borrow(),
},
sin_zero,
}
}
}

impl SockaddrIn6 {
#[allow(clippy::unnecessary_cast)]
pub fn from_libc(l: &::libc::sockaddr_in6) -> Self {
Self {
sin6_family: Rc::new(RefCell::new(l.sin6_family as u16)),
sin6_port: Rc::new(RefCell::new(l.sin6_port)),
sin6_flowinfo: Rc::new(RefCell::new(l.sin6_flowinfo)),
sin6_addr: Rc::new(RefCell::new(In6Addr {
s6_addr: Rc::new(RefCell::new(
l.sin6_addr.s6_addr.to_vec().into_boxed_slice(),
)),
})),
sin6_scope_id: Rc::new(RefCell::new(l.sin6_scope_id)),
}
}

pub fn from_ipv6(addr: &::std::net::Ipv6Addr, port: u16) -> Self {
let s = Self::default();
*s.sin6_family.borrow_mut() = ::libc::AF_INET6 as u16;
*s.sin6_port.borrow_mut() = port.to_be();
s.sin6_addr
.borrow()
.s6_addr
.borrow_mut()
.copy_from_slice(&addr.octets());
s
}

#[cfg(target_os = "linux")]
pub fn to_libc(&self) -> ::libc::sockaddr_in6 {
let mut s6_addr = [0u8; 16];
s6_addr.copy_from_slice(&self.sin6_addr.borrow().s6_addr.borrow());
::libc::sockaddr_in6 {
sin6_family: *self.sin6_family.borrow(),
sin6_port: *self.sin6_port.borrow(),
sin6_flowinfo: *self.sin6_flowinfo.borrow(),
sin6_addr: ::libc::in6_addr { s6_addr },
sin6_scope_id: *self.sin6_scope_id.borrow(),
}
}
}

impl Default for Sockaddr {
fn default() -> Self {
Self {
Expand Down
44 changes: 44 additions & 0 deletions rules/ifaddrs/tgt_refcount.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,47 @@ use libcc2rs::*;
fn t1() -> libcc2rs::Ifaddrs {
Default::default()
}

fn f1(a0: Ptr<Ptr<Ifaddrs>>) -> i32 {
let __out = a0.clone();
match nix::ifaddrs::getifaddrs() {
Ok(__ifas) => {
let __list: Vec<nix::ifaddrs::InterfaceAddress> = __ifas.collect();
let mut __next = Ptr::<Ifaddrs>::null();
for __ifa in __list.iter().rev() {
let __node = Ifaddrs::from_interface_address(__ifa);
*__node.ifa_next.borrow_mut() = __next.clone();
__next = Ptr::alloc(__node);
}
__out.write(__next);
0
}
Err(__e) => {
libcc2rs::cpp2rust_errno().write(__e as i32);
-1
}
}
}

fn f2(a0: Ptr<Ifaddrs>) {
let mut __cur = a0.clone();
while !__cur.is_null() {
let __next = __cur.with(|__i| {
let __name = __i.ifa_name.borrow();
if !__name.is_null() {
__name.delete_array();
}
let __addr = __i.ifa_addr.borrow();
if !__addr.is_null() {
__addr.delete();
}
let __mask = __i.ifa_netmask.borrow();
if !__mask.is_null() {
__mask.delete();
}
(*__i.ifa_next.borrow()).clone()
});
__cur.delete();
__cur = __next;
}
}
105 changes: 105 additions & 0 deletions rules/netdb/tgt_refcount.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,108 @@ use libcc2rs::*;
fn t1() -> libcc2rs::Addrinfo {
Default::default()
}

fn f1(a0: Ptr<u8>, a1: Ptr<u8>, a2: Ptr<Addrinfo>, a3: Ptr<Ptr<Addrinfo>>) -> i32 {
let __node = a0.clone();
let __service = a1.clone();
let __hints = a2.clone();
let __out = a3.clone();
let __family = if __hints.is_null() {
::libc::AF_UNSPEC
} else {
__hints.with(|__h| *__h.ai_family.borrow())
};
let __socktype = if __hints.is_null() {
0
} else {
__hints.with(|__h| *__h.ai_socktype.borrow())
};
let __protocol = if __hints.is_null() {
0
} else {
__hints.with(|__h| *__h.ai_protocol.borrow())
};
let __port: u16 = if __service.is_null() {
0
} else {
__service.to_rust_string().parse().unwrap_or(0)
};
let mut __addrs: Vec<::std::net::IpAddr> = Vec::new();
if __node.is_null() {
if __family == ::libc::AF_INET6 {
__addrs.push(::std::net::IpAddr::V6(::std::net::Ipv6Addr::UNSPECIFIED));
} else {
__addrs.push(::std::net::IpAddr::V4(::std::net::Ipv4Addr::UNSPECIFIED));
}
} else {
let __host = __node.to_rust_string();
match __host.parse::<::std::net::IpAddr>() {
Ok(__ip) => __addrs.push(__ip),
Err(_) => {
use ::std::net::ToSocketAddrs;
match (__host.as_str(), __port).to_socket_addrs() {
Ok(__it) => {
for __sa in __it {
__addrs.push(__sa.ip());
}
}
Err(_) => {}
}
}
}
}
__addrs.retain(|__ip| match __family {
::libc::AF_INET => __ip.is_ipv4(),
::libc::AF_INET6 => __ip.is_ipv6(),
_ => true,
});
if __addrs.is_empty() {
::libc::EAI_NONAME
} else {
let mut __next = Ptr::<Addrinfo>::null();
for __ip in __addrs.iter().rev() {
let __ai = Addrinfo::default();
*__ai.ai_socktype.borrow_mut() = __socktype;
*__ai.ai_protocol.borrow_mut() = __protocol;
let __storage = Ptr::alloc(SockaddrStorage::default());
match __ip {
::std::net::IpAddr::V4(__v4) => {
*__ai.ai_family.borrow_mut() = ::libc::AF_INET;
*__ai.ai_addrlen.borrow_mut() =
::std::mem::size_of::<::libc::sockaddr_in>() as u32;
__storage
.reinterpret_cast::<SockaddrIn>()
.write(SockaddrIn::from_ipv4(__v4, __port));
}
::std::net::IpAddr::V6(__v6) => {
*__ai.ai_family.borrow_mut() = ::libc::AF_INET6;
*__ai.ai_addrlen.borrow_mut() =
::std::mem::size_of::<::libc::sockaddr_in6>() as u32;
__storage
.reinterpret_cast::<SockaddrIn6>()
.write(SockaddrIn6::from_ipv6(__v6, __port));
}
}
*__ai.ai_addr.borrow_mut() = __storage.reinterpret_cast::<Sockaddr>();
*__ai.ai_next.borrow_mut() = __next.clone();
__next = Ptr::alloc(__ai);
}
__out.write(__next);
0
}
}

fn f2(a0: Ptr<Addrinfo>) {
let mut __cur = a0.clone();
while !__cur.is_null() {
let __next = __cur.with(|__ai| {
let __addr = __ai.ai_addr.borrow();
if !__addr.is_null() {
__addr.delete();
}
(*__ai.ai_next.borrow()).clone()
});
__cur.delete();
__cur = __next;
}
}
8 changes: 8 additions & 0 deletions rules/socket/src.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,11 @@ ssize_t f19(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen) {
return sendto(sockfd, buf, len, flags, dest_addr, addrlen);
}

int f20() {
return AF_INET;
}

int f21() {
return AF_INET6;
}
8 changes: 8 additions & 0 deletions rules/socket/tgt_unsafe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,11 @@ unsafe fn f19(
) -> isize {
libc::sendto(a0, a1, a2, a3, a4, a5)
}

unsafe fn f20() -> i32 {
libc::AF_INET
}

unsafe fn f21() -> i32 {
libc::AF_INET6
}
36 changes: 36 additions & 0 deletions tests/unit/ifaddrs.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#include <assert.h>
#include <ifaddrs.h>
#include <netinet/in.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>

int main(void) {
struct ifaddrs *list = NULL;
assert(getifaddrs(&list) == 0);
assert(list != NULL);
int found_loopback = 0;
struct ifaddrs *ifa;
for (ifa = list; ifa != NULL; ifa = ifa->ifa_next) {
assert(ifa->ifa_name != NULL);
if (ifa->ifa_addr == NULL) {
continue;
}
if (ifa->ifa_addr->sa_family != AF_INET) {
continue;
}
struct sockaddr_in *sin = (struct sockaddr_in *)ifa->ifa_addr;
unsigned char lo_be[4] = {127, 0, 0, 1};
if (memcmp(&sin->sin_addr, lo_be, 4) == 0) {
found_loopback = 1;
assert(ifa->ifa_flags != 0);
assert(ifa->ifa_netmask != NULL);
struct sockaddr_in *mask = (struct sockaddr_in *)ifa->ifa_netmask;
unsigned char mask_be[4] = {255, 0, 0, 0};
assert(memcmp(&mask->sin_addr, mask_be, 4) == 0);
}
}
assert(found_loopback);
freeifaddrs(list);
return 0;
}
Loading
Loading