diff --git a/rules/src/modules.rs b/rules/src/modules.rs index 9920f88..2de39d9 100644 --- a/rules/src/modules.rs +++ b/rules/src/modules.rs @@ -72,6 +72,8 @@ pub mod stdio_tgt_unsafe; pub mod string_tgt_refcount; #[path = r#"../string/tgt_unsafe.rs"#] pub mod string_tgt_unsafe; +#[path = r#"../time/tgt_unsafe.rs"#] +pub mod time_tgt_unsafe; #[path = r#"../unique_ptr/tgt_refcount.rs"#] pub mod unique_ptr_tgt_refcount; #[path = r#"../unique_ptr/tgt_unsafe.rs"#] diff --git a/rules/time/ir_unsafe.json b/rules/time/ir_unsafe.json new file mode 100644 index 0000000..2073ad0 --- /dev/null +++ b/rules/time/ir_unsafe.json @@ -0,0 +1,281 @@ +{ + "f1": { + "body": [ + { + "text": "libc::time(" + }, + { + "placeholder": { + "arg": 0, + "access": "read" + } + }, + { + "text": ")" + } + ], + "params": { + "a0": { + "type": "*mut i64", + "is_unsafe_pointer": true + } + }, + "return_type": { + "type": "i64" + } + }, + "f2": { + "body": [ + { + "text": "libc::gettimeofday(" + }, + { + "placeholder": { + "arg": 0, + "access": "read" + } + }, + { + "text": ", " + }, + { + "placeholder": { + "arg": 1, + "access": "read" + } + }, + { + "text": " as *mut ::libc::timezone)" + } + ], + "params": { + "a0": { + "type": "*mut ::libc::timeval", + "is_unsafe_pointer": true + }, + "a1": { + "type": "*mut ::libc::timezone", + "is_unsafe_pointer": true + } + }, + "return_type": { + "type": "i32" + } + }, + "f3": { + "body": [ + { + "text": "libc::clock_gettime(" + }, + { + "placeholder": { + "arg": 0, + "access": "read" + } + }, + { + "text": " as ::libc::clockid_t, " + }, + { + "placeholder": { + "arg": 1, + "access": "read" + } + }, + { + "text": ")" + } + ], + "params": { + "a0": { + "type": "::libc::clockid_t" + }, + "a1": { + "type": "*mut ::libc::timespec", + "is_unsafe_pointer": true + } + }, + "return_type": { + "type": "i32" + } + }, + "f4": { + "body": [ + { + "text": "libc::localtime_r(" + }, + { + "placeholder": { + "arg": 0, + "access": "read" + } + }, + { + "text": ", " + }, + { + "placeholder": { + "arg": 1, + "access": "read" + } + }, + { + "text": ")" + } + ], + "params": { + "a0": { + "type": "*const i64", + "is_unsafe_pointer": true + }, + "a1": { + "type": "*mut ::libc::tm", + "is_unsafe_pointer": true + } + }, + "return_type": { + "type": "*mut ::libc::tm", + "is_unsafe_pointer": true + } + }, + "f5": { + "body": [ + { + "text": "libc::gmtime_r(" + }, + { + "placeholder": { + "arg": 0, + "access": "read" + } + }, + { + "text": ", " + }, + { + "placeholder": { + "arg": 1, + "access": "read" + } + }, + { + "text": ")" + } + ], + "params": { + "a0": { + "type": "*const i64", + "is_unsafe_pointer": true + }, + "a1": { + "type": "*mut ::libc::tm", + "is_unsafe_pointer": true + } + }, + "return_type": { + "type": "*mut ::libc::tm", + "is_unsafe_pointer": true + } + }, + "f6": { + "body": [ + { + "text": "libc::strftime(" + }, + { + "placeholder": { + "arg": 0, + "access": "read" + } + }, + { + "text": " as *mut i8, " + }, + { + "placeholder": { + "arg": 1, + "access": "read" + } + }, + { + "text": " as usize, " + }, + { + "placeholder": { + "arg": 2, + "access": "read" + } + }, + { + "text": " as *const i8, " + }, + { + "placeholder": { + "arg": 3, + "access": "read" + } + }, + { + "text": ") as u64" + } + ], + "params": { + "a0": { + "type": "*mut u8", + "is_unsafe_pointer": true + }, + "a1": { + "type": "u64" + }, + "a2": { + "type": "*const u8", + "is_unsafe_pointer": true + }, + "a3": { + "type": "*const ::libc::tm", + "is_unsafe_pointer": true + } + }, + "return_type": { + "type": "u64" + } + }, + "f7": { + "body": [ + { + "text": "libc::utimes(" + }, + { + "placeholder": { + "arg": 0, + "access": "read" + } + }, + { + "text": " as *const i8, " + }, + { + "placeholder": { + "arg": 1, + "access": "read" + } + }, + { + "text": ")" + } + ], + "params": { + "a0": { + "type": "*const u8", + "is_unsafe_pointer": true + }, + "a1": { + "type": "*const ::libc::timeval", + "is_unsafe_pointer": true + } + }, + "return_type": { + "type": "i32" + } + } +} diff --git a/rules/time/src.cpp b/rules/time/src.cpp new file mode 100644 index 0000000..6043602 --- /dev/null +++ b/rules/time/src.cpp @@ -0,0 +1,29 @@ +// Copyright (c) 2022-present INESC-ID. +// Distributed under the MIT license that can be found in the LICENSE file. + +#include +#include + +time_t f1(time_t *tloc) { return time(tloc); } + +int f2(struct timeval *tv, struct timezone *tz) { + return gettimeofday(tv, tz); +} + +int f3(clockid_t clk_id, struct timespec *tp) { return clock_gettime(clk_id, tp); } + +struct tm *f4(const time_t *timep, struct tm *result) { + return localtime_r(timep, result); +} + +struct tm *f5(const time_t *timep, struct tm *result) { + return gmtime_r(timep, result); +} + +size_t f6(char *s, size_t max, const char *fmt, const struct tm *tm) { + return strftime(s, max, fmt, tm); +} + +int f7(const char *filename, const struct timeval times[2]) { + return utimes(filename, times); +} diff --git a/rules/time/tgt_unsafe.rs b/rules/time/tgt_unsafe.rs new file mode 100644 index 0000000..40c736f --- /dev/null +++ b/rules/time/tgt_unsafe.rs @@ -0,0 +1,30 @@ +// Copyright (c) 2022-present INESC-ID. +// Distributed under the MIT license that can be found in the LICENSE file. + +unsafe fn f1(a0: *mut i64) -> i64 { + libc::time(a0) +} + +unsafe fn f2(a0: *mut ::libc::timeval, a1: *mut ::libc::timezone) -> i32 { + libc::gettimeofday(a0, a1 as *mut ::libc::timezone) +} + +unsafe fn f3(a0: ::libc::clockid_t, a1: *mut ::libc::timespec) -> i32 { + libc::clock_gettime(a0 as ::libc::clockid_t, a1) +} + +unsafe fn f4(a0: *const i64, a1: *mut ::libc::tm) -> *mut ::libc::tm { + libc::localtime_r(a0, a1) +} + +unsafe fn f5(a0: *const i64, a1: *mut ::libc::tm) -> *mut ::libc::tm { + libc::gmtime_r(a0, a1) +} + +unsafe fn f6(a0: *mut u8, a1: u64, a2: *const u8, a3: *const ::libc::tm) -> u64 { + libc::strftime(a0 as *mut i8, a1 as usize, a2 as *const i8, a3) as u64 +} + +unsafe fn f7(a0: *const u8, a1: *const ::libc::timeval) -> i32 { + libc::utimes(a0 as *const i8, a1) +} diff --git a/tests/unit/out/unsafe/time_h.rs b/tests/unit/out/unsafe/time_h.rs new file mode 100644 index 0000000..6048857 --- /dev/null +++ b/tests/unit/out/unsafe/time_h.rs @@ -0,0 +1,147 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::{Read, Seek, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +pub unsafe fn test_time_0() { + assert!(((((libc::time(std::ptr::null_mut())) > (0_i64)) as i32) != 0)); +} +pub unsafe fn test_gettimeofday_1() { + let mut tv: timeval = std::mem::zeroed::(); + tv.tv_sec = 0_i64; + tv.tv_usec = 0_i64; + assert!( + ((((libc::gettimeofday( + (&mut tv as *mut timeval), + (0 as *mut ::libc::c_void) as *mut ::libc::timezone + )) == (0)) as i32) + != 0) + ); + assert!(((((tv.tv_sec) > (0_i64)) as i32) != 0)); + assert!(((((tv.tv_usec) >= (0_i64)) as i32) != 0)); + assert!(((((tv.tv_usec) < (1000000_i64)) as i32) != 0)); +} +pub unsafe fn test_clock_gettime_2() { + let mut ts: timespec = std::mem::zeroed::(); + ts.tv_sec = 0_i64; + ts.tv_nsec = 0_i64; + assert!(((((libc::clock_gettime(1, (&mut ts as *mut timespec))) == (0)) as i32) != 0)); + assert!(((((ts.tv_sec) > (0_i64)) as i32) != 0)); + assert!(((((ts.tv_nsec) >= (0_i64)) as i32) != 0)); + assert!(((((ts.tv_nsec) < (1000000000_i64)) as i32) != 0)); +} +pub unsafe fn test_localtime_r_3() { + let mut t: i64 = 0_i64; + let mut tm: tm = std::mem::zeroed::(); + assert!( + (((!((libc::localtime_r((&mut t as *mut i64).cast_const(), (&mut tm as *mut tm))) + .is_null())) as i32) + != 0) + ); + assert!(((((tm.tm_year) == (70)) as i32) != 0)); +} +pub unsafe fn test_gmtime_r_4() { + let mut t: i64 = 0_i64; + let mut tm: tm = std::mem::zeroed::(); + assert!( + (((!((libc::gmtime_r((&mut t as *mut i64).cast_const(), (&mut tm as *mut tm))).is_null())) + as i32) + != 0) + ); + assert!(((((tm.tm_year) == (70)) as i32) != 0)); + assert!(((((tm.tm_mon) == (0)) as i32) != 0)); + assert!(((((tm.tm_mday) == (1)) as i32) != 0)); + assert!(((((tm.tm_hour) == (0)) as i32) != 0)); +} +pub unsafe fn test_strftime_5() { + let mut t: i64 = 0_i64; + let mut tm: tm = std::mem::zeroed::(); + libc::gmtime_r((&mut t as *mut i64).cast_const(), (&mut tm as *mut tm)); + let mut buf: [u8; 64] = [0_u8; 64]; + assert!( + ((((libc::strftime( + buf.as_mut_ptr() as *mut i8, + ::std::mem::size_of::<[u8; 64]>() as u64 as usize, + (b"%Y-%m-%d\0".as_ptr().cast_mut()).cast_const() as *const i8, + (&mut tm as *mut tm).cast_const() + ) as u64) + == (10_u64)) as i32) + != 0) + ); + assert!( + ((((libc::strcmp( + (buf.as_mut_ptr()).cast_const() as *const i8, + (b"1970-01-01\0".as_ptr().cast_mut()).cast_const() as *const i8 + )) == (0)) as i32) + != 0) + ); +} +pub unsafe fn test_utimes_6() { + let mut path: *const u8 = (b"/tmp/cpp2rust_utimes_test.tmp\0".as_ptr().cast_mut()).cast_const(); + let mut fp: *mut ::std::fs::File = + match std::ffi::CStr::from_ptr((b"wb\0".as_ptr().cast_mut()).cast_const() as *const i8) + .to_str() + .expect("invalid c-string") + { + v if v == "rb" => std::fs::OpenOptions::new() + .read(true) + .open( + std::ffi::CStr::from_ptr(path as *const i8) + .to_str() + .expect("invalid c-string"), + ) + .ok() + .map_or(std::ptr::null_mut(), |f| Box::into_raw(Box::new(f))), + v if v == "wb" => std::fs::OpenOptions::new() + .write(true) + .create(true) + .truncate(true) + .open( + std::ffi::CStr::from_ptr(path as *const i8) + .to_str() + .expect("invalid c-string"), + ) + .ok() + .map_or(std::ptr::null_mut(), |f| Box::into_raw(Box::new(f))), + _ => panic!("unsupported mode"), + }; + assert!((((!((fp).is_null())) as i32) != 0)); + assert!( + (((({ + Box::from_raw(fp); + 0 + }) == (0)) as i32) + != 0) + ); + let mut tv: [timeval; 2] = [std::mem::zeroed::(); 2]; + tv[(0) as usize].tv_sec = 1000_i64; + tv[(0) as usize].tv_usec = 0_i64; + tv[(1) as usize].tv_sec = 2000_i64; + tv[(1) as usize].tv_usec = 0_i64; + assert!( + ((((libc::utimes(path as *const i8, (tv.as_mut_ptr()).cast_const())) == (0)) as i32) != 0) + ); + libc::unlink(path as *const i8); + assert!( + ((((libc::utimes(path as *const i8, (tv.as_mut_ptr()).cast_const())) == (-1_i32)) as i32) + != 0) + ); +} +pub fn main() { + unsafe { + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + (unsafe { test_time_0() }); + (unsafe { test_gettimeofday_1() }); + (unsafe { test_clock_gettime_2() }); + (unsafe { test_localtime_r_3() }); + (unsafe { test_gmtime_r_4() }); + (unsafe { test_strftime_5() }); + (unsafe { test_utimes_6() }); + return 0; +} diff --git a/tests/unit/time_h.c b/tests/unit/time_h.c new file mode 100644 index 0000000..0cc6026 --- /dev/null +++ b/tests/unit/time_h.c @@ -0,0 +1,82 @@ +// no-compile: refcount +#include +#include +#include +#include +#include +#include +#include + +static void test_time(void) { assert(time(NULL) > 0); } + +static void test_gettimeofday(void) { + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = 0; + assert(gettimeofday(&tv, NULL) == 0); + assert(tv.tv_sec > 0); + assert(tv.tv_usec >= 0); + assert(tv.tv_usec < 1000000); +} + +static void test_clock_gettime(void) { + struct timespec ts; + ts.tv_sec = 0; + ts.tv_nsec = 0; + assert(clock_gettime(CLOCK_MONOTONIC, &ts) == 0); + assert(ts.tv_sec > 0); + assert(ts.tv_nsec >= 0); + assert(ts.tv_nsec < 1000000000); +} + +static void test_localtime_r(void) { + time_t t = 0; + struct tm tm; + assert(localtime_r(&t, &tm) != NULL); + assert(tm.tm_year == 70); +} + +static void test_gmtime_r(void) { + time_t t = 0; + struct tm tm; + assert(gmtime_r(&t, &tm) != NULL); + assert(tm.tm_year == 70); + assert(tm.tm_mon == 0); + assert(tm.tm_mday == 1); + assert(tm.tm_hour == 0); +} + +static void test_strftime(void) { + time_t t = 0; + struct tm tm; + gmtime_r(&t, &tm); + char buf[64]; + assert(strftime(buf, sizeof(buf), "%Y-%m-%d", &tm) == 10); + assert(strcmp(buf, "1970-01-01") == 0); +} + +static void test_utimes(void) { + const char *path = "/tmp/cpp2rust_utimes_test.tmp"; + FILE *fp = fopen(path, "wb"); + assert(fp != NULL); + assert(fclose(fp) == 0); + struct timeval tv[2]; + tv[0].tv_sec = 1000; + tv[0].tv_usec = 0; + tv[1].tv_sec = 2000; + tv[1].tv_usec = 0; + assert(utimes(path, tv) == 0); + unlink(path); + assert(utimes(path, tv) == -1); +} + +int main(void) { + test_time(); + test_gettimeofday(); + test_clock_gettime(); + test_localtime_r(); + test_gmtime_r(); + test_strftime(); + test_utimes(); + return 0; +}