From 545cccbc9d50413a205bbbd9653d2bece247f830 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Sat, 18 Jul 2026 16:44:42 +0100 Subject: [PATCH 1/5] Add safe socket rules --- libcc2rs/src/libc_shims/socket.rs | 47 +++++++- rules/socket/tgt_refcount.rs | 101 ++++++++++++++++++ .../out/refcount/socket_transparent_union.rs | 55 ++++++++++ tests/unit/socket_transparent_union.c | 1 - 4 files changed, 202 insertions(+), 2 deletions(-) create mode 100644 tests/unit/out/refcount/socket_transparent_union.rs diff --git a/libcc2rs/src/libc_shims/socket.rs b/libcc2rs/src/libc_shims/socket.rs index 954184e9..a74e6518 100644 --- a/libcc2rs/src/libc_shims/socket.rs +++ b/libcc2rs/src/libc_shims/socket.rs @@ -2,7 +2,7 @@ // Distributed under the MIT license that can be found in the LICENSE file. use super::{In6Addr, InAddr}; -use crate::{ByteRepr, Value}; +use crate::{ByteRepr, Ptr, Value}; use std::cell::RefCell; use std::rc::Rc; @@ -304,3 +304,48 @@ impl ByteRepr for ::libc::sockaddr_in {} impl ByteRepr for ::libc::sockaddr_in6 {} impl ByteRepr for ::libc::sockaddr_un {} impl ByteRepr for ::libc::sockaddr_storage {} + +pub fn decode_sockaddr( + addr: &Ptr, + _len: u32, +) -> Option> { + let family = addr.reinterpret_cast::().read(); + if family == ::libc::AF_INET as u16 { + let m = addr.reinterpret_cast::().read(); + Some(Box::new(nix::sys::socket::SockaddrIn::from(m.to_libc()))) + } else if family == ::libc::AF_INET6 as u16 { + let m = addr.reinterpret_cast::().read(); + Some(Box::new(nix::sys::socket::SockaddrIn6::from(m.to_libc()))) + } else if family == ::libc::AF_UNIX as u16 { + let m = addr.reinterpret_cast::().read(); + let path = m.sun_path.borrow(); + let end = path.iter().position(|&c| c == 0).unwrap_or(path.len()); + nix::sys::socket::UnixAddr::new(&path[..end]) + .ok() + .map(|u| Box::new(u) as Box) + } else { + None + } +} + +pub fn encode_sockaddr( + ss: &nix::sys::socket::SockaddrStorage, + out: &Ptr, + out_len: &Ptr, +) { + use nix::sys::socket::{AddressFamily, SockaddrLike}; + match ss.family() { + Some(AddressFamily::Inet) => { + let l = ::libc::sockaddr_in::from(*ss.as_sockaddr_in().unwrap()); + out.reinterpret_cast::() + .write(SockaddrIn::from_libc(&l)); + } + Some(AddressFamily::Inet6) => { + let l = ::libc::sockaddr_in6::from(*ss.as_sockaddr_in6().unwrap()); + out.reinterpret_cast::() + .write(SockaddrIn6::from_libc(&l)); + } + _ => {} + } + out_len.write(ss.len()); +} diff --git a/rules/socket/tgt_refcount.rs b/rules/socket/tgt_refcount.rs index 5d591a14..f4541604 100644 --- a/rules/socket/tgt_refcount.rs +++ b/rules/socket/tgt_refcount.rs @@ -15,6 +15,107 @@ fn t3() -> libcc2rs::SockaddrUn { Default::default() } +fn f12(a0: i32, a1: Ptr, a2: Ptr) -> i32 { + match nix::sys::socket::getsockname::(a0) { + Ok(__ss) => { + libcc2rs::encode_sockaddr(&__ss, &a1, &a2); + 0 + } + Err(__e) => { + libcc2rs::cpp2rust_errno().write(__e as i32); + -1 + } + } +} + +fn f13(a0: i32, a1: Ptr, a2: u32) -> i32 { + match libcc2rs::decode_sockaddr(&a1, a2) { + Some(__addr) => match nix::sys::socket::connect(a0, &*__addr) { + Ok(()) => 0, + Err(__e) => { + libcc2rs::cpp2rust_errno().write(__e as i32); + -1 + } + }, + None => { + libcc2rs::cpp2rust_errno().write(::libc::EAFNOSUPPORT); + -1 + } + } +} + +fn f14(a0: i32, a1: Ptr, a2: Ptr) -> i32 { + match nix::sys::socket::getpeername::(a0) { + Ok(__ss) => { + libcc2rs::encode_sockaddr(&__ss, &a1, &a2); + 0 + } + Err(__e) => { + libcc2rs::cpp2rust_errno().write(__e as i32); + -1 + } + } +} + +fn f16(a0: i32, a1: Ptr, a2: u32) -> i32 { + match libcc2rs::decode_sockaddr(&a1, a2) { + Some(__addr) => match nix::sys::socket::bind(a0, &*__addr) { + Ok(()) => 0, + Err(__e) => { + libcc2rs::cpp2rust_errno().write(__e as i32); + -1 + } + }, + None => { + libcc2rs::cpp2rust_errno().write(::libc::EAFNOSUPPORT); + -1 + } + } +} + +fn f18(a0: i32, a1: AnyPtr, a2: usize, a3: i32, a4: Ptr, a5: Ptr) -> isize { + let __buf = a1.reinterpret_cast::(); + match __buf.with_slice_mut(a2, |__s| { + nix::sys::socket::recvfrom::(a0, __s) + }) { + Ok((__n, __from)) => { + match __from { + Some(__ss) => libcc2rs::encode_sockaddr(&__ss, &a4, &a5), + None => {} + } + __n as isize + } + Err(__e) => { + libcc2rs::cpp2rust_errno().write(__e as i32); + -1 + } + } +} + +fn f19(a0: i32, a1: AnyPtr, a2: usize, a3: i32, a4: Ptr, a5: u32) -> isize { + let __buf = a1.reinterpret_cast::(); + match libcc2rs::decode_sockaddr(&a4, a5) { + Some(__addr) => match __buf.with_slice(a2, |__s| { + nix::sys::socket::sendto( + a0, + __s, + &*__addr, + nix::sys::socket::MsgFlags::from_bits_truncate(a3), + ) + }) { + Ok(__n) => __n as isize, + Err(__e) => { + libcc2rs::cpp2rust_errno().write(__e as i32); + -1 + } + }, + None => { + libcc2rs::cpp2rust_errno().write(::libc::EAFNOSUPPORT); + -1 + } + } +} + fn f9(a0: i32, a1: AnyPtr, a2: usize, a3: i32) -> isize { let __buf = a1.reinterpret_cast::(); match __buf.with_slice_mut(a2, |__s| { diff --git a/tests/unit/out/refcount/socket_transparent_union.rs b/tests/unit/out/refcount/socket_transparent_union.rs new file mode 100644 index 00000000..7477a81c --- /dev/null +++ b/tests/unit/out/refcount/socket_transparent_union.rs @@ -0,0 +1,55 @@ +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 fd: Value = Rc::new(RefCell::new(0)); + let ssloc: Value = Rc::new(RefCell::new(Default::default())); + let slen: Value = Rc::new(RefCell::new((128usize as u32))); + assert!( + (((match nix::sys::socket::getsockname::((*fd.borrow())) + { + Ok(__ss) => { + libcc2rs::encode_sockaddr( + &__ss, + &(ssloc.as_pointer()).reinterpret_cast::(), + &(slen.as_pointer()), + ); + 0 + } + Err(__e) => { + libcc2rs::cpp2rust_errno().write(__e as i32); + -1 + } + } == -1_i32) as i32) + != 0) + ); + let sin: Value = Rc::new(RefCell::new(Default::default())); + let inlen: Value = Rc::new(RefCell::new((16usize as u32))); + assert!( + (((match nix::sys::socket::getsockname::((*fd.borrow())) + { + Ok(__ss) => { + libcc2rs::encode_sockaddr( + &__ss, + &(sin.as_pointer()).reinterpret_cast::(), + &(inlen.as_pointer()), + ); + 0 + } + Err(__e) => { + libcc2rs::cpp2rust_errno().write(__e as i32); + -1 + } + } == -1_i32) as i32) + != 0) + ); + return 0; +} diff --git a/tests/unit/socket_transparent_union.c b/tests/unit/socket_transparent_union.c index 7ee4b865..05cecd69 100644 --- a/tests/unit/socket_transparent_union.c +++ b/tests/unit/socket_transparent_union.c @@ -1,4 +1,3 @@ -// no-compile: refcount #define _GNU_SOURCE #include #include From 4c2dc3c5810964ee9e68682b37f868b1c453ae4d Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Sat, 18 Jul 2026 16:51:31 +0100 Subject: [PATCH 2/5] Move encode/decode inside Sockaddr --- libcc2rs/src/libc_shims/socket.rs | 76 +++++++++---------- rules/socket/tgt_refcount.rs | 12 +-- .../out/refcount/socket_transparent_union.rs | 4 +- 3 files changed, 45 insertions(+), 47 deletions(-) diff --git a/libcc2rs/src/libc_shims/socket.rs b/libcc2rs/src/libc_shims/socket.rs index a74e6518..c8ab59d1 100644 --- a/libcc2rs/src/libc_shims/socket.rs +++ b/libcc2rs/src/libc_shims/socket.rs @@ -305,47 +305,45 @@ impl ByteRepr for ::libc::sockaddr_in6 {} impl ByteRepr for ::libc::sockaddr_un {} impl ByteRepr for ::libc::sockaddr_storage {} -pub fn decode_sockaddr( - addr: &Ptr, - _len: u32, -) -> Option> { - let family = addr.reinterpret_cast::().read(); - if family == ::libc::AF_INET as u16 { - let m = addr.reinterpret_cast::().read(); - Some(Box::new(nix::sys::socket::SockaddrIn::from(m.to_libc()))) - } else if family == ::libc::AF_INET6 as u16 { - let m = addr.reinterpret_cast::().read(); - Some(Box::new(nix::sys::socket::SockaddrIn6::from(m.to_libc()))) - } else if family == ::libc::AF_UNIX as u16 { - let m = addr.reinterpret_cast::().read(); - let path = m.sun_path.borrow(); - let end = path.iter().position(|&c| c == 0).unwrap_or(path.len()); - nix::sys::socket::UnixAddr::new(&path[..end]) - .ok() - .map(|u| Box::new(u) as Box) - } else { - None +impl Sockaddr { + pub fn decode( + addr: &Ptr, + _len: u32, + ) -> Option> { + let family = addr.reinterpret_cast::().read(); + if family == ::libc::AF_INET as u16 { + let m = addr.reinterpret_cast::().read(); + Some(Box::new(nix::sys::socket::SockaddrIn::from(m.to_libc()))) + } else if family == ::libc::AF_INET6 as u16 { + let m = addr.reinterpret_cast::().read(); + Some(Box::new(nix::sys::socket::SockaddrIn6::from(m.to_libc()))) + } else if family == ::libc::AF_UNIX as u16 { + let m = addr.reinterpret_cast::().read(); + let path = m.sun_path.borrow(); + let end = path.iter().position(|&c| c == 0).unwrap_or(path.len()); + nix::sys::socket::UnixAddr::new(&path[..end]) + .ok() + .map(|u| Box::new(u) as Box) + } else { + None + } } -} -pub fn encode_sockaddr( - ss: &nix::sys::socket::SockaddrStorage, - out: &Ptr, - out_len: &Ptr, -) { - use nix::sys::socket::{AddressFamily, SockaddrLike}; - match ss.family() { - Some(AddressFamily::Inet) => { - let l = ::libc::sockaddr_in::from(*ss.as_sockaddr_in().unwrap()); - out.reinterpret_cast::() - .write(SockaddrIn::from_libc(&l)); - } - Some(AddressFamily::Inet6) => { - let l = ::libc::sockaddr_in6::from(*ss.as_sockaddr_in6().unwrap()); - out.reinterpret_cast::() - .write(SockaddrIn6::from_libc(&l)); + pub fn encode(ss: &nix::sys::socket::SockaddrStorage, out: &Ptr, out_len: &Ptr) { + use nix::sys::socket::{AddressFamily, SockaddrLike}; + match ss.family() { + Some(AddressFamily::Inet) => { + let l = ::libc::sockaddr_in::from(*ss.as_sockaddr_in().unwrap()); + out.reinterpret_cast::() + .write(SockaddrIn::from_libc(&l)); + } + Some(AddressFamily::Inet6) => { + let l = ::libc::sockaddr_in6::from(*ss.as_sockaddr_in6().unwrap()); + out.reinterpret_cast::() + .write(SockaddrIn6::from_libc(&l)); + } + _ => {} } - _ => {} + out_len.write(ss.len()); } - out_len.write(ss.len()); } diff --git a/rules/socket/tgt_refcount.rs b/rules/socket/tgt_refcount.rs index f4541604..67dcb270 100644 --- a/rules/socket/tgt_refcount.rs +++ b/rules/socket/tgt_refcount.rs @@ -18,7 +18,7 @@ fn t3() -> libcc2rs::SockaddrUn { fn f12(a0: i32, a1: Ptr, a2: Ptr) -> i32 { match nix::sys::socket::getsockname::(a0) { Ok(__ss) => { - libcc2rs::encode_sockaddr(&__ss, &a1, &a2); + Sockaddr::encode(&__ss, &a1, &a2); 0 } Err(__e) => { @@ -29,7 +29,7 @@ fn f12(a0: i32, a1: Ptr, a2: Ptr) -> i32 { } fn f13(a0: i32, a1: Ptr, a2: u32) -> i32 { - match libcc2rs::decode_sockaddr(&a1, a2) { + match Sockaddr::decode(&a1, a2) { Some(__addr) => match nix::sys::socket::connect(a0, &*__addr) { Ok(()) => 0, Err(__e) => { @@ -47,7 +47,7 @@ fn f13(a0: i32, a1: Ptr, a2: u32) -> i32 { fn f14(a0: i32, a1: Ptr, a2: Ptr) -> i32 { match nix::sys::socket::getpeername::(a0) { Ok(__ss) => { - libcc2rs::encode_sockaddr(&__ss, &a1, &a2); + Sockaddr::encode(&__ss, &a1, &a2); 0 } Err(__e) => { @@ -58,7 +58,7 @@ fn f14(a0: i32, a1: Ptr, a2: Ptr) -> i32 { } fn f16(a0: i32, a1: Ptr, a2: u32) -> i32 { - match libcc2rs::decode_sockaddr(&a1, a2) { + match Sockaddr::decode(&a1, a2) { Some(__addr) => match nix::sys::socket::bind(a0, &*__addr) { Ok(()) => 0, Err(__e) => { @@ -80,7 +80,7 @@ fn f18(a0: i32, a1: AnyPtr, a2: usize, a3: i32, a4: Ptr, a5: Ptr) }) { Ok((__n, __from)) => { match __from { - Some(__ss) => libcc2rs::encode_sockaddr(&__ss, &a4, &a5), + Some(__ss) => Sockaddr::encode(&__ss, &a4, &a5), None => {} } __n as isize @@ -94,7 +94,7 @@ fn f18(a0: i32, a1: AnyPtr, a2: usize, a3: i32, a4: Ptr, a5: Ptr) fn f19(a0: i32, a1: AnyPtr, a2: usize, a3: i32, a4: Ptr, a5: u32) -> isize { let __buf = a1.reinterpret_cast::(); - match libcc2rs::decode_sockaddr(&a4, a5) { + match Sockaddr::decode(&a4, a5) { Some(__addr) => match __buf.with_slice(a2, |__s| { nix::sys::socket::sendto( a0, diff --git a/tests/unit/out/refcount/socket_transparent_union.rs b/tests/unit/out/refcount/socket_transparent_union.rs index 7477a81c..8ff1ea8c 100644 --- a/tests/unit/out/refcount/socket_transparent_union.rs +++ b/tests/unit/out/refcount/socket_transparent_union.rs @@ -17,7 +17,7 @@ fn main_0() -> i32 { (((match nix::sys::socket::getsockname::((*fd.borrow())) { Ok(__ss) => { - libcc2rs::encode_sockaddr( + Sockaddr::encode( &__ss, &(ssloc.as_pointer()).reinterpret_cast::(), &(slen.as_pointer()), @@ -37,7 +37,7 @@ fn main_0() -> i32 { (((match nix::sys::socket::getsockname::((*fd.borrow())) { Ok(__ss) => { - libcc2rs::encode_sockaddr( + Sockaddr::encode( &__ss, &(sin.as_pointer()).reinterpret_cast::(), &(inlen.as_pointer()), From 52f7b19670a68f94dc10e48f90209e43d1bad710 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Sat, 18 Jul 2026 20:08:26 +0100 Subject: [PATCH 3/5] Update tests --- tests/unit/out/unsafe/stdlib_h.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/out/unsafe/stdlib_h.rs b/tests/unit/out/unsafe/stdlib_h.rs index 674bcb94..a61ef3ad 100644 --- a/tests/unit/out/unsafe/stdlib_h.rs +++ b/tests/unit/out/unsafe/stdlib_h.rs @@ -70,7 +70,7 @@ pub unsafe fn test_realpath_1() { .is_null()) as i32) != 0) ); - assert!(((((*libcc2rs::cpp2rust_errno_unsafe()) == (2)) as i32) != 0)); + assert!(((((*libcc2rs::cpp2rust_errno_unsafe()) == (libc::ENOENT)) as i32) != 0)); } pub fn main() { unsafe { From e0ad2c9a173a7fb1dc55bc7540fc31634e484dde Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Sat, 18 Jul 2026 20:16:43 +0100 Subject: [PATCH 4/5] Add to_libc for macos --- libcc2rs/src/libc_shims/socket.rs | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/libcc2rs/src/libc_shims/socket.rs b/libcc2rs/src/libc_shims/socket.rs index c8ab59d1..d3f61eba 100644 --- a/libcc2rs/src/libc_shims/socket.rs +++ b/libcc2rs/src/libc_shims/socket.rs @@ -77,6 +77,21 @@ impl SockaddrIn { sin_zero, } } + + #[cfg(target_os = "macos")] + 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_len: ::std::mem::size_of::<::libc::sockaddr_in>() as u8, + sin_family: *self.sin_family.borrow() as u8, + sin_port: *self.sin_port.borrow(), + sin_addr: ::libc::in_addr { + s_addr: *self.sin_addr.borrow().s_addr.borrow(), + }, + sin_zero, + } + } } impl SockaddrIn6 { @@ -119,6 +134,20 @@ impl SockaddrIn6 { sin6_scope_id: *self.sin6_scope_id.borrow(), } } + + #[cfg(target_os = "macos")] + 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_len: ::std::mem::size_of::<::libc::sockaddr_in6>() as u8, + sin6_family: *self.sin6_family.borrow() as u8, + 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 { From 0ffac9029a7f7604f0d96e7962d9d711b5d77fac Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Sat, 18 Jul 2026 20:27:17 +0100 Subject: [PATCH 5/5] Use i8 array --- libcc2rs/src/libc_shims/socket.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libcc2rs/src/libc_shims/socket.rs b/libcc2rs/src/libc_shims/socket.rs index d3f61eba..3b15500a 100644 --- a/libcc2rs/src/libc_shims/socket.rs +++ b/libcc2rs/src/libc_shims/socket.rs @@ -80,8 +80,10 @@ impl SockaddrIn { #[cfg(target_os = "macos")] pub fn to_libc(&self) -> ::libc::sockaddr_in { - let mut sin_zero = [0u8; 8]; - sin_zero.copy_from_slice(&self.sin_zero.borrow()); + let mut sin_zero = [0i8; 8]; + for (dst, src) in sin_zero.iter_mut().zip(self.sin_zero.borrow().iter()) { + *dst = *src as i8; + } ::libc::sockaddr_in { sin_len: ::std::mem::size_of::<::libc::sockaddr_in>() as u8, sin_family: *self.sin_family.borrow() as u8,