Skip to content

Commit c443aa0

Browse files
authored
Add safe errno (#256)
Safe errno is a global Value in libcc2rs. Refcount rules will write the correct errno number into this global Value
1 parent 9d1d39e commit c443aa0

7 files changed

Lines changed: 98 additions & 15 deletions

File tree

libcc2rs/src/compat.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
// Copyright (c) 2022-present INESC-ID.
22
// Distributed under the MIT license that can be found in the LICENSE file.
33

4+
use std::cell::RefCell;
45
use std::ffi::c_void;
6+
use std::rc::Rc;
7+
8+
use crate::rc::Ptr;
9+
use crate::{AsPointer, Value};
510

611
unsafe extern "C" {
712
#[cfg(target_os = "linux")]
@@ -40,6 +45,14 @@ pub unsafe fn malloc_usable_size(ptr: *mut c_void) -> usize {
4045
/// # Safety
4146
///
4247
/// Invokes the platform specific errno.
43-
pub unsafe fn cpp2rust_errno() -> *mut i32 {
48+
pub unsafe fn cpp2rust_errno_unsafe() -> *mut i32 {
4449
unsafe { platform_errno_location() }
4550
}
51+
52+
thread_local! {
53+
static ERRNO: Value<i32> = Rc::new(RefCell::new(0));
54+
}
55+
56+
pub fn cpp2rust_errno() -> Ptr<i32> {
57+
ERRNO.with(AsPointer::as_pointer)
58+
}

rules/errno/tgt_refcount.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
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+
fn f1() -> Ptr<i32> {
7+
libcc2rs::cpp2rust_errno()
8+
}

rules/errno/tgt_unsafe.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
// Distributed under the MIT license that can be found in the LICENSE file.
33

44
unsafe fn f1() -> *mut i32 {
5-
libcc2rs::cpp2rust_errno()
5+
libcc2rs::cpp2rust_errno_unsafe()
66
}

rules/src/modules.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ pub mod deque_tgt_refcount;
4040
pub mod deque_tgt_unsafe;
4141
#[path = r#"../dirent/tgt_unsafe.rs"#]
4242
pub mod dirent_tgt_unsafe;
43+
#[path = r#"../errno/tgt_refcount.rs"#]
44+
pub mod errno_tgt_refcount;
4345
#[path = r#"../errno/tgt_unsafe.rs"#]
4446
pub mod errno_tgt_unsafe;
4547
#[path = r#"../eventfd/tgt_unsafe.rs"#]

tests/unit/errno.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// no-compile: refcount
1+
// panic: refcount
22
#include <assert.h>
33
#include <errno.h>
44
#include <stdio.h>

tests/unit/out/refcount/errno.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
extern crate libcc2rs;
2+
use libcc2rs::*;
3+
use std::cell::RefCell;
4+
use std::collections::BTreeMap;
5+
use std::io::prelude::*;
6+
use std::io::{Read, Seek, Write};
7+
use std::os::fd::AsFd;
8+
use std::rc::{Rc, Weak};
9+
pub fn test_errno_0() {
10+
libcc2rs::cpp2rust_errno().write(0);
11+
assert!(((((libcc2rs::cpp2rust_errno().read()) == 0) as i32) != 0));
12+
libcc2rs::cpp2rust_errno().write(42);
13+
assert!(((((libcc2rs::cpp2rust_errno().read()) == 42) as i32) != 0));
14+
let saved: Value<i32> = Rc::new(RefCell::new((libcc2rs::cpp2rust_errno().read())));
15+
assert!(((((*saved.borrow()) == 42) as i32) != 0));
16+
libcc2rs::cpp2rust_errno().write(0);
17+
}
18+
pub fn test_errno_preserved_across_strdup_1() {
19+
libcc2rs::cpp2rust_errno().write(99);
20+
let d: Value<Ptr<u8>> = Rc::new(RefCell::new(libcc2rs::strdup_refcount(
21+
Ptr::from_string_literal(b"hello"),
22+
)));
23+
assert!((((!((*d.borrow()).is_null())) as i32) != 0));
24+
assert!(((((libcc2rs::cpp2rust_errno().read()) == 99) as i32) != 0));
25+
libcc2rs::free_refcount(((*d.borrow()).clone() as Ptr<u8>).to_any());
26+
libcc2rs::cpp2rust_errno().write(0);
27+
}
28+
pub fn test_errno_from_fseek_2() {
29+
libcc2rs::cpp2rust_errno().write(0);
30+
let r: Value<i32> = Rc::new(RefCell::new(
31+
if (match 0 {
32+
0 => libcc2rs::cin().with_mut(|__v: &mut ::std::fs::File| {
33+
__v.seek(std::io::SeekFrom::Start(0_i64 as u64))
34+
}),
35+
1 => libcc2rs::cin()
36+
.with_mut(|__v: &mut ::std::fs::File| __v.seek(std::io::SeekFrom::Current(0_i64))),
37+
2 => libcc2rs::cin()
38+
.with_mut(|__v: &mut ::std::fs::File| __v.seek(std::io::SeekFrom::End(0_i64))),
39+
_ => Err(std::io::Error::other("unsupported whence for fseek.")),
40+
})
41+
.is_ok()
42+
{
43+
0
44+
} else {
45+
-1
46+
},
47+
));
48+
assert!(((((*r.borrow()) == -1_i32) as i32) != 0));
49+
assert!(((((libcc2rs::cpp2rust_errno().read()) == 29) as i32) != 0));
50+
libcc2rs::cpp2rust_errno().write(0);
51+
}
52+
pub fn main() {
53+
std::process::exit(main_0());
54+
}
55+
fn main_0() -> i32 {
56+
({ test_errno_0() });
57+
({ test_errno_preserved_across_strdup_1() });
58+
({ test_errno_from_fseek_2() });
59+
return 0;
60+
}

tests/unit/out/unsafe/errno.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,29 +7,29 @@ use std::io::{Read, Seek, Write};
77
use std::os::fd::{AsFd, FromRawFd, IntoRawFd};
88
use std::rc::Rc;
99
pub unsafe fn test_errno_0() {
10-
(*libcc2rs::cpp2rust_errno()) = 0;
11-
assert!(((((*libcc2rs::cpp2rust_errno()) == (0)) as i32) != 0));
12-
(*libcc2rs::cpp2rust_errno()) = 42;
13-
assert!(((((*libcc2rs::cpp2rust_errno()) == (42)) as i32) != 0));
14-
let mut saved: i32 = (*libcc2rs::cpp2rust_errno());
10+
(*libcc2rs::cpp2rust_errno_unsafe()) = 0;
11+
assert!(((((*libcc2rs::cpp2rust_errno_unsafe()) == (0)) as i32) != 0));
12+
(*libcc2rs::cpp2rust_errno_unsafe()) = 42;
13+
assert!(((((*libcc2rs::cpp2rust_errno_unsafe()) == (42)) as i32) != 0));
14+
let mut saved: i32 = (*libcc2rs::cpp2rust_errno_unsafe());
1515
assert!(((((saved) == (42)) as i32) != 0));
16-
(*libcc2rs::cpp2rust_errno()) = 0;
16+
(*libcc2rs::cpp2rust_errno_unsafe()) = 0;
1717
}
1818
pub unsafe fn test_errno_preserved_across_strdup_1() {
19-
(*libcc2rs::cpp2rust_errno()) = 99;
19+
(*libcc2rs::cpp2rust_errno_unsafe()) = 99;
2020
let mut d: *mut libc::c_char =
2121
libcc2rs::strdup_unsafe((c"hello".as_ptr().cast_mut()).cast_const());
2222
assert!((((!((d).is_null())) as i32) != 0));
23-
assert!(((((*libcc2rs::cpp2rust_errno()) == (99)) as i32) != 0));
23+
assert!(((((*libcc2rs::cpp2rust_errno_unsafe()) == (99)) as i32) != 0));
2424
libcc2rs::free_unsafe((d as *mut libc::c_char as *mut ::libc::c_void));
25-
(*libcc2rs::cpp2rust_errno()) = 0;
25+
(*libcc2rs::cpp2rust_errno_unsafe()) = 0;
2626
}
2727
pub unsafe fn test_errno_from_fseek_2() {
28-
(*libcc2rs::cpp2rust_errno()) = 0;
28+
(*libcc2rs::cpp2rust_errno_unsafe()) = 0;
2929
let mut r: i32 = libc::fseek(libcc2rs::stdin_unsafe(), 0_i64 as ::libc::c_long, 0);
3030
assert!(((((r) == (-1_i32)) as i32) != 0));
31-
assert!(((((*libcc2rs::cpp2rust_errno()) == (29)) as i32) != 0));
32-
(*libcc2rs::cpp2rust_errno()) = 0;
31+
assert!(((((*libcc2rs::cpp2rust_errno_unsafe()) == (29)) as i32) != 0));
32+
(*libcc2rs::cpp2rust_errno_unsafe()) = 0;
3333
}
3434
pub fn main() {
3535
unsafe {

0 commit comments

Comments
 (0)