From 1f92cc1ea1678830a5ab6135f8b97822298eb637 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Thu, 9 Jul 2026 12:15:20 +0100 Subject: [PATCH 1/2] Add safe errno --- libcc2rs/src/compat.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/libcc2rs/src/compat.rs b/libcc2rs/src/compat.rs index 38873938..3ef0b5d8 100644 --- a/libcc2rs/src/compat.rs +++ b/libcc2rs/src/compat.rs @@ -1,7 +1,12 @@ // Copyright (c) 2022-present INESC-ID. // Distributed under the MIT license that can be found in the LICENSE file. +use std::cell::RefCell; use std::ffi::c_void; +use std::rc::Rc; + +use crate::rc::Ptr; +use crate::{AsPointer, Value}; unsafe extern "C" { #[cfg(target_os = "linux")] @@ -43,3 +48,11 @@ pub unsafe fn malloc_usable_size(ptr: *mut c_void) -> usize { pub unsafe fn cpp2rust_errno() -> *mut i32 { unsafe { platform_errno_location() } } + +thread_local! { + static ERRNO: Value = Rc::new(RefCell::new(0)); +} + +pub fn cpp2rust_errno() -> Ptr { + ERRNO.with(AsPointer::as_pointer) +} From 7d0132893f3dcccefea1aba9656f7c6b699a6e6e Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Mon, 13 Jul 2026 22:46:49 +0100 Subject: [PATCH 2/2] Use safe errno in rules --- libcc2rs/src/compat.rs | 2 +- rules/errno/tgt_refcount.rs | 8 +++++ rules/errno/tgt_unsafe.rs | 2 +- rules/src/modules.rs | 2 ++ tests/unit/errno.c | 2 +- tests/unit/out/refcount/errno.rs | 60 ++++++++++++++++++++++++++++++++ tests/unit/out/unsafe/errno.rs | 24 ++++++------- 7 files changed, 85 insertions(+), 15 deletions(-) create mode 100644 rules/errno/tgt_refcount.rs create mode 100644 tests/unit/out/refcount/errno.rs diff --git a/libcc2rs/src/compat.rs b/libcc2rs/src/compat.rs index 3ef0b5d8..2729e810 100644 --- a/libcc2rs/src/compat.rs +++ b/libcc2rs/src/compat.rs @@ -45,7 +45,7 @@ pub unsafe fn malloc_usable_size(ptr: *mut c_void) -> usize { /// # Safety /// /// Invokes the platform specific errno. -pub unsafe fn cpp2rust_errno() -> *mut i32 { +pub unsafe fn cpp2rust_errno_unsafe() -> *mut i32 { unsafe { platform_errno_location() } } diff --git a/rules/errno/tgt_refcount.rs b/rules/errno/tgt_refcount.rs new file mode 100644 index 00000000..8220480e --- /dev/null +++ b/rules/errno/tgt_refcount.rs @@ -0,0 +1,8 @@ +// Copyright (c) 2022-present INESC-ID. +// Distributed under the MIT license that can be found in the LICENSE file. + +use libcc2rs::*; + +fn f1() -> Ptr { + libcc2rs::cpp2rust_errno() +} diff --git a/rules/errno/tgt_unsafe.rs b/rules/errno/tgt_unsafe.rs index 57796bc2..1e2cc13f 100644 --- a/rules/errno/tgt_unsafe.rs +++ b/rules/errno/tgt_unsafe.rs @@ -2,5 +2,5 @@ // Distributed under the MIT license that can be found in the LICENSE file. unsafe fn f1() -> *mut i32 { - libcc2rs::cpp2rust_errno() + libcc2rs::cpp2rust_errno_unsafe() } diff --git a/rules/src/modules.rs b/rules/src/modules.rs index 53112eed..e873ed19 100644 --- a/rules/src/modules.rs +++ b/rules/src/modules.rs @@ -40,6 +40,8 @@ pub mod deque_tgt_refcount; pub mod deque_tgt_unsafe; #[path = r#"../dirent/tgt_unsafe.rs"#] pub mod dirent_tgt_unsafe; +#[path = r#"../errno/tgt_refcount.rs"#] +pub mod errno_tgt_refcount; #[path = r#"../errno/tgt_unsafe.rs"#] pub mod errno_tgt_unsafe; #[path = r#"../eventfd/tgt_unsafe.rs"#] diff --git a/tests/unit/errno.c b/tests/unit/errno.c index 8a0be0bf..9f9f0e3f 100644 --- a/tests/unit/errno.c +++ b/tests/unit/errno.c @@ -1,4 +1,4 @@ -// no-compile: refcount +// panic: refcount #include #include #include diff --git a/tests/unit/out/refcount/errno.rs b/tests/unit/out/refcount/errno.rs new file mode 100644 index 00000000..653f5b96 --- /dev/null +++ b/tests/unit/out/refcount/errno.rs @@ -0,0 +1,60 @@ +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 test_errno_0() { + libcc2rs::cpp2rust_errno().write(0); + assert!(((((libcc2rs::cpp2rust_errno().read()) == 0) as i32) != 0)); + libcc2rs::cpp2rust_errno().write(42); + assert!(((((libcc2rs::cpp2rust_errno().read()) == 42) as i32) != 0)); + let saved: Value = Rc::new(RefCell::new((libcc2rs::cpp2rust_errno().read()))); + assert!(((((*saved.borrow()) == 42) as i32) != 0)); + libcc2rs::cpp2rust_errno().write(0); +} +pub fn test_errno_preserved_across_strdup_1() { + libcc2rs::cpp2rust_errno().write(99); + let d: Value> = Rc::new(RefCell::new(libcc2rs::strdup_refcount( + Ptr::from_string_literal(b"hello"), + ))); + assert!((((!((*d.borrow()).is_null())) as i32) != 0)); + assert!(((((libcc2rs::cpp2rust_errno().read()) == 99) as i32) != 0)); + libcc2rs::free_refcount(((*d.borrow()).clone() as Ptr).to_any()); + libcc2rs::cpp2rust_errno().write(0); +} +pub fn test_errno_from_fseek_2() { + libcc2rs::cpp2rust_errno().write(0); + let r: Value = Rc::new(RefCell::new( + if (match 0 { + 0 => libcc2rs::cin().with_mut(|__v: &mut ::std::fs::File| { + __v.seek(std::io::SeekFrom::Start(0_i64 as u64)) + }), + 1 => libcc2rs::cin() + .with_mut(|__v: &mut ::std::fs::File| __v.seek(std::io::SeekFrom::Current(0_i64))), + 2 => libcc2rs::cin() + .with_mut(|__v: &mut ::std::fs::File| __v.seek(std::io::SeekFrom::End(0_i64))), + _ => Err(std::io::Error::other("unsupported whence for fseek.")), + }) + .is_ok() + { + 0 + } else { + -1 + }, + )); + assert!(((((*r.borrow()) == -1_i32) as i32) != 0)); + assert!(((((libcc2rs::cpp2rust_errno().read()) == 29) as i32) != 0)); + libcc2rs::cpp2rust_errno().write(0); +} +pub fn main() { + std::process::exit(main_0()); +} +fn main_0() -> i32 { + ({ test_errno_0() }); + ({ test_errno_preserved_across_strdup_1() }); + ({ test_errno_from_fseek_2() }); + return 0; +} diff --git a/tests/unit/out/unsafe/errno.rs b/tests/unit/out/unsafe/errno.rs index 5a5e67a0..0e36fbbb 100644 --- a/tests/unit/out/unsafe/errno.rs +++ b/tests/unit/out/unsafe/errno.rs @@ -7,29 +7,29 @@ use std::io::{Read, Seek, Write}; use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; use std::rc::Rc; pub unsafe fn test_errno_0() { - (*libcc2rs::cpp2rust_errno()) = 0; - assert!(((((*libcc2rs::cpp2rust_errno()) == (0)) as i32) != 0)); - (*libcc2rs::cpp2rust_errno()) = 42; - assert!(((((*libcc2rs::cpp2rust_errno()) == (42)) as i32) != 0)); - let mut saved: i32 = (*libcc2rs::cpp2rust_errno()); + (*libcc2rs::cpp2rust_errno_unsafe()) = 0; + assert!(((((*libcc2rs::cpp2rust_errno_unsafe()) == (0)) as i32) != 0)); + (*libcc2rs::cpp2rust_errno_unsafe()) = 42; + assert!(((((*libcc2rs::cpp2rust_errno_unsafe()) == (42)) as i32) != 0)); + let mut saved: i32 = (*libcc2rs::cpp2rust_errno_unsafe()); assert!(((((saved) == (42)) as i32) != 0)); - (*libcc2rs::cpp2rust_errno()) = 0; + (*libcc2rs::cpp2rust_errno_unsafe()) = 0; } pub unsafe fn test_errno_preserved_across_strdup_1() { - (*libcc2rs::cpp2rust_errno()) = 99; + (*libcc2rs::cpp2rust_errno_unsafe()) = 99; let mut d: *mut libc::c_char = libcc2rs::strdup_unsafe((c"hello".as_ptr().cast_mut()).cast_const()); assert!((((!((d).is_null())) as i32) != 0)); - assert!(((((*libcc2rs::cpp2rust_errno()) == (99)) as i32) != 0)); + assert!(((((*libcc2rs::cpp2rust_errno_unsafe()) == (99)) as i32) != 0)); libcc2rs::free_unsafe((d as *mut libc::c_char as *mut ::libc::c_void)); - (*libcc2rs::cpp2rust_errno()) = 0; + (*libcc2rs::cpp2rust_errno_unsafe()) = 0; } pub unsafe fn test_errno_from_fseek_2() { - (*libcc2rs::cpp2rust_errno()) = 0; + (*libcc2rs::cpp2rust_errno_unsafe()) = 0; let mut r: i32 = libc::fseek(libcc2rs::stdin_unsafe(), 0_i64 as ::libc::c_long, 0); assert!(((((r) == (-1_i32)) as i32) != 0)); - assert!(((((*libcc2rs::cpp2rust_errno()) == (29)) as i32) != 0)); - (*libcc2rs::cpp2rust_errno()) = 0; + assert!(((((*libcc2rs::cpp2rust_errno_unsafe()) == (29)) as i32) != 0)); + (*libcc2rs::cpp2rust_errno_unsafe()) = 0; } pub fn main() { unsafe {