diff --git a/libcc2rs/Cargo.toml b/libcc2rs/Cargo.toml index afea73e..6221433 100644 --- a/libcc2rs/Cargo.toml +++ b/libcc2rs/Cargo.toml @@ -5,3 +5,4 @@ edition = "2024" [dependencies] libcc2rs-macros = { path = "../libcc2rs-macros", version = "0.1.0" } +libc = "0.2" diff --git a/libcc2rs/src/alloc.rs b/libcc2rs/src/alloc.rs new file mode 100644 index 0000000..0f9a5e5 --- /dev/null +++ b/libcc2rs/src/alloc.rs @@ -0,0 +1,37 @@ +// Copyright (c) 2022-present INESC-ID. +// Distributed under the MIT license that can be found in the LICENSE file. + +/// # Safety +/// +/// Same contract as C's `malloc`. +pub unsafe fn malloc_unsafe(a0: u64) -> *mut libc::c_void { + unsafe { libc::malloc(a0 as libc::size_t) } +} + +/// # Safety +/// +/// Same contract as C's `free`. +pub unsafe fn free_unsafe(a0: *mut libc::c_void) { + unsafe { libc::free(a0) } +} + +/// # Safety +/// +/// Same contract as C's `realloc`. +pub unsafe fn realloc_unsafe(a0: *mut libc::c_void, a1: u64) -> *mut libc::c_void { + unsafe { libc::realloc(a0, a1 as libc::size_t) } +} + +/// # Safety +/// +/// Same contract as C's `calloc`. +pub unsafe fn calloc_unsafe(a0: u64, a1: u64) -> *mut libc::c_void { + unsafe { libc::calloc(a0 as libc::size_t, a1 as libc::size_t) } +} + +/// # Safety +/// +/// Same contract as C's `strdup`. +pub unsafe fn strdup_unsafe(a0: *const u8) -> *mut u8 { + unsafe { libc::strdup(a0 as *const libc::c_char) as *mut u8 } +} diff --git a/libcc2rs/src/lib.rs b/libcc2rs/src/lib.rs index 859ba5c..4288464 100644 --- a/libcc2rs/src/lib.rs +++ b/libcc2rs/src/lib.rs @@ -22,6 +22,9 @@ pub use rules::*; mod io; pub use io::*; +mod alloc; +pub use alloc::*; + mod iterators; pub use iterators::*; diff --git a/rules/cstdlib/ir_unsafe.json b/rules/cstdlib/ir_unsafe.json index d32581a..7bb7bb5 100644 --- a/rules/cstdlib/ir_unsafe.json +++ b/rules/cstdlib/ir_unsafe.json @@ -9,7 +9,7 @@ "f2": { "body": [ { - "text": "libc::free(" + "text": "libcc2rs::free_unsafe(" }, { "placeholder": { @@ -31,7 +31,7 @@ "f3": { "body": [ { - "text": "libc::malloc(" + "text": "libcc2rs::malloc_unsafe(" }, { "placeholder": { @@ -40,7 +40,7 @@ } }, { - "text": " as ::libc::size_t)" + "text": ")" } ], "params": { @@ -56,7 +56,7 @@ "f4": { "body": [ { - "text": "libc::realloc(" + "text": "libcc2rs::realloc_unsafe(" }, { "placeholder": { @@ -74,7 +74,7 @@ } }, { - "text": " as ::libc::size_t)" + "text": ")" } ], "params": { @@ -94,7 +94,7 @@ "f5": { "body": [ { - "text": "libc::calloc(" + "text": "libcc2rs::calloc_unsafe(" }, { "placeholder": { @@ -103,7 +103,7 @@ } }, { - "text": " as ::libc::size_t, " + "text": ", " }, { "placeholder": { @@ -112,7 +112,7 @@ } }, { - "text": " as ::libc::size_t)" + "text": ")" } ], "params": { diff --git a/rules/cstdlib/tgt_unsafe.rs b/rules/cstdlib/tgt_unsafe.rs index 0cad5a4..953b07e 100644 --- a/rules/cstdlib/tgt_unsafe.rs +++ b/rules/cstdlib/tgt_unsafe.rs @@ -6,19 +6,19 @@ unsafe fn f1() { } unsafe fn f2(a0: *mut ::libc::c_void) { - libc::free(a0) + libcc2rs::free_unsafe(a0) } unsafe fn f3(a0: u64) -> *mut ::libc::c_void { - libc::malloc(a0 as ::libc::size_t) + libcc2rs::malloc_unsafe(a0) } unsafe fn f4(a0: *mut ::libc::c_void, a1: u64) -> *mut ::libc::c_void { - libc::realloc(a0, a1 as ::libc::size_t) + libcc2rs::realloc_unsafe(a0, a1) } unsafe fn f5(a0: u64, a1: u64) -> *mut ::libc::c_void { - libc::calloc(a0 as ::libc::size_t, a1 as ::libc::size_t) + libcc2rs::calloc_unsafe(a0, a1) } unsafe fn f6(a0: *const u8) -> *mut u8 { diff --git a/rules/cstring/ir_unsafe.json b/rules/cstring/ir_unsafe.json index 62e6890..c39d845 100644 --- a/rules/cstring/ir_unsafe.json +++ b/rules/cstring/ir_unsafe.json @@ -283,7 +283,7 @@ "f15": { "body": [ { - "text": "libc::strdup(" + "text": "libcc2rs::strdup_unsafe(" }, { "placeholder": { @@ -292,7 +292,7 @@ } }, { - "text": " as *const i8) as *mut u8" + "text": ")" } ], "params": { diff --git a/rules/cstring/tgt_unsafe.rs b/rules/cstring/tgt_unsafe.rs index 192f0de..9ab40a8 100644 --- a/rules/cstring/tgt_unsafe.rs +++ b/rules/cstring/tgt_unsafe.rs @@ -77,7 +77,7 @@ unsafe fn f14(a0: *mut u8, a1: i32) -> *mut u8 { } unsafe fn f15(a0: *const u8) -> *mut u8 { - libc::strdup(a0 as *const i8) as *mut u8 + libcc2rs::strdup_unsafe(a0) } unsafe fn f16(a0: *const u8, a1: *const u8) -> u64 { diff --git a/tests/unit/malloc_realloc_free.c b/tests/unit/malloc_realloc_free.c index afd3d9e..643f8d9 100644 --- a/tests/unit/malloc_realloc_free.c +++ b/tests/unit/malloc_realloc_free.c @@ -2,37 +2,49 @@ #include #include -int main() { - int *p = (int *)malloc(sizeof(int)); - *p = 42; - assert(*p == 42); - free(p); +#define ALLOC_TESTS(MALLOC, FREE, REALLOC, CALLOC) \ + do { \ + int *p = (int *)MALLOC(sizeof(int)); \ + *p = 42; \ + assert(*p == 42); \ + FREE(p); \ + \ + int *arr = (int *)MALLOC(4 * sizeof(int)); \ + for (int i = 0; i < 4; i++) { \ + arr[i] = i * 10; \ + } \ + assert(arr[0] == 0); \ + assert(arr[3] == 30); \ + FREE(arr); \ + \ + int *grow = (int *)MALLOC(2 * sizeof(int)); \ + grow[0] = 1; \ + grow[1] = 2; \ + grow = (int *)REALLOC(grow, 4 * sizeof(int)); \ + grow[2] = 3; \ + grow[3] = 4; \ + assert(grow[0] == 1); \ + assert(grow[1] == 2); \ + assert(grow[2] == 3); \ + assert(grow[3] == 4); \ + FREE(grow); \ + \ + int *zeros = (int *)CALLOC(4, sizeof(int)); \ + for (int i = 0; i < 4; i++) { \ + assert(zeros[i] == 0); \ + } \ + FREE(zeros); \ + } while (0) - int *arr = (int *)malloc(4 * sizeof(int)); - for (int i = 0; i < 4; i++) { - arr[i] = i * 10; - } - assert(arr[0] == 0); - assert(arr[3] == 30); - free(arr); +int main() { + ALLOC_TESTS(malloc, free, realloc, calloc); - int *grow = (int *)malloc(2 * sizeof(int)); - grow[0] = 1; - grow[1] = 2; - grow = (int *)realloc(grow, 4 * sizeof(int)); - grow[2] = 3; - grow[3] = 4; - assert(grow[0] == 1); - assert(grow[1] == 2); - assert(grow[2] == 3); - assert(grow[3] == 4); - free(grow); + void *(*pmalloc)(size_t) = malloc; + void (*pfree)(void *) = free; + void *(*prealloc)(void *, size_t) = realloc; + void *(*pcalloc)(size_t, size_t) = calloc; - int *zeros = (int *)calloc(4, sizeof(int)); - for (int i = 0; i < 4; i++) { - assert(zeros[i] == 0); - } - free(zeros); + ALLOC_TESTS(pmalloc, pfree, prealloc, pcalloc); return 0; } diff --git a/tests/unit/out/unsafe/cstring.rs b/tests/unit/out/unsafe/cstring.rs index 32afbc9..be5deaa 100644 --- a/tests/unit/out/unsafe/cstring.rs +++ b/tests/unit/out/unsafe/cstring.rs @@ -267,7 +267,7 @@ pub unsafe fn test_strrchr_9() { ); } pub unsafe fn test_strdup_10() { - let mut d: *mut u8 = libc::strdup(b"hello\0".as_ptr() as *const i8) as *mut u8; + let mut d: *mut u8 = libcc2rs::strdup_unsafe(b"hello\0".as_ptr()); assert!(!((d).is_null())); assert!( ((libc::strcmp( @@ -275,14 +275,14 @@ pub unsafe fn test_strdup_10() { b"hello\0".as_ptr() as *const i8 )) == (0)) ); - libc::free((d as *mut u8 as *mut ::libc::c_void)); + libcc2rs::free_unsafe((d as *mut u8 as *mut ::libc::c_void)); let mut p: *const u8 = b"world\0".as_ptr(); let mut buf: [u8; 4] = [('a' as u8), ('b' as u8), ('c' as u8), ('\0' as u8)]; - let mut d2: *mut u8 = libc::strdup(p as *const i8) as *mut u8; + let mut d2: *mut u8 = libcc2rs::strdup_unsafe(p); assert!(!((d2).is_null())); assert!(((libc::strcmp((d2).cast_const() as *const i8, p as *const i8)) == (0))); - libc::free((d2 as *mut u8 as *mut ::libc::c_void)); - let mut d3: *mut u8 = libc::strdup((buf.as_mut_ptr()).cast_const() as *const i8) as *mut u8; + libcc2rs::free_unsafe((d2 as *mut u8 as *mut ::libc::c_void)); + let mut d3: *mut u8 = libcc2rs::strdup_unsafe((buf.as_mut_ptr()).cast_const()); assert!(!((d3).is_null())); assert!( ((libc::strcmp( @@ -290,7 +290,7 @@ pub unsafe fn test_strdup_10() { (buf.as_mut_ptr()).cast_const() as *const i8 )) == (0)) ); - libc::free((d3 as *mut u8 as *mut ::libc::c_void)); + libcc2rs::free_unsafe((d3 as *mut u8 as *mut ::libc::c_void)); } pub unsafe fn test_strcspn_11() { assert!( diff --git a/tests/unit/out/unsafe/errno.rs b/tests/unit/out/unsafe/errno.rs index d0f8f8e..4073499 100644 --- a/tests/unit/out/unsafe/errno.rs +++ b/tests/unit/out/unsafe/errno.rs @@ -17,11 +17,10 @@ pub unsafe fn test_errno_0() { } pub unsafe fn test_errno_preserved_across_strdup_1() { (*libcc2rs::cpp2rust_errno()) = 99; - let mut d: *mut u8 = - libc::strdup((b"hello\0".as_ptr().cast_mut()).cast_const() as *const i8) as *mut u8; + let mut d: *mut u8 = libcc2rs::strdup_unsafe((b"hello\0".as_ptr().cast_mut()).cast_const()); assert!((((!((d).is_null())) as i32) != 0)); assert!(((((*libcc2rs::cpp2rust_errno()) == (99)) as i32) != 0)); - libc::free((d as *mut u8 as *mut ::libc::c_void)); + libcc2rs::free_unsafe((d as *mut u8 as *mut ::libc::c_void)); (*libcc2rs::cpp2rust_errno()) = 0; } pub unsafe fn test_errno_from_fseek_2() { diff --git a/tests/unit/out/unsafe/malloc_realloc_free.rs b/tests/unit/out/unsafe/malloc_realloc_free.rs index 77d5074..a1ff1d1 100644 --- a/tests/unit/out/unsafe/malloc_realloc_free.rs +++ b/tests/unit/out/unsafe/malloc_realloc_free.rs @@ -12,47 +12,121 @@ pub fn main() { } } unsafe fn main_0() -> i32 { - let mut p: *mut i32 = - (libc::malloc(::std::mem::size_of::() as u64 as ::libc::size_t) as *mut i32); - (*p) = 42; - assert!(((((*p) == (42)) as i32) != 0)); - libc::free((p as *mut i32 as *mut ::libc::c_void)); - let mut arr: *mut i32 = (libc::malloc( - (4_u64).wrapping_mul(::std::mem::size_of::() as u64 as u64) as ::libc::size_t, - ) as *mut i32); - let mut i: i32 = 0; - 'loop_: while ((((i) < (4)) as i32) != 0) { - (*arr.offset((i) as isize)) = ((i) * (10)); - i.postfix_inc(); + 'loop_: loop { + let mut p: *mut i32 = + (libcc2rs::malloc_unsafe(::std::mem::size_of::() as u64) as *mut i32); + (*p) = 42; + assert!(((((*p) == (42)) as i32) != 0)); + libcc2rs::free_unsafe((p as *mut i32 as *mut ::libc::c_void)); + let mut arr: *mut i32 = (libcc2rs::malloc_unsafe( + (4_u64).wrapping_mul(::std::mem::size_of::() as u64 as u64), + ) as *mut i32); + let mut i: i32 = 0; + 'loop_: while ((((i) < (4)) as i32) != 0) { + (*arr.offset((i) as isize)) = ((i) * (10)); + i.postfix_inc(); + } + assert!(((((*arr.offset((0) as isize)) == (0)) as i32) != 0)); + assert!(((((*arr.offset((3) as isize)) == (30)) as i32) != 0)); + libcc2rs::free_unsafe((arr as *mut i32 as *mut ::libc::c_void)); + let mut grow: *mut i32 = (libcc2rs::malloc_unsafe( + (2_u64).wrapping_mul(::std::mem::size_of::() as u64 as u64), + ) as *mut i32); + (*grow.offset((0) as isize)) = 1; + (*grow.offset((1) as isize)) = 2; + grow = (libcc2rs::realloc_unsafe( + (grow as *mut i32 as *mut ::libc::c_void), + (4_u64).wrapping_mul(::std::mem::size_of::() as u64 as u64), + ) as *mut i32); + (*grow.offset((2) as isize)) = 3; + (*grow.offset((3) as isize)) = 4; + assert!(((((*grow.offset((0) as isize)) == (1)) as i32) != 0)); + assert!(((((*grow.offset((1) as isize)) == (2)) as i32) != 0)); + assert!(((((*grow.offset((2) as isize)) == (3)) as i32) != 0)); + assert!(((((*grow.offset((3) as isize)) == (4)) as i32) != 0)); + libcc2rs::free_unsafe((grow as *mut i32 as *mut ::libc::c_void)); + let mut zeros: *mut i32 = + (libcc2rs::calloc_unsafe(4_u64, ::std::mem::size_of::() as u64) as *mut i32); + let mut i: i32 = 0; + 'loop_: while ((((i) < (4)) as i32) != 0) { + assert!(((((*zeros.offset((i) as isize)) == (0)) as i32) != 0)); + i.postfix_inc(); + } + libcc2rs::free_unsafe((zeros as *mut i32 as *mut ::libc::c_void)); + if !(0 != 0) { + break; + } } - assert!(((((*arr.offset((0) as isize)) == (0)) as i32) != 0)); - assert!(((((*arr.offset((3) as isize)) == (30)) as i32) != 0)); - libc::free((arr as *mut i32 as *mut ::libc::c_void)); - let mut grow: *mut i32 = (libc::malloc( - (2_u64).wrapping_mul(::std::mem::size_of::() as u64 as u64) as ::libc::size_t, - ) as *mut i32); - (*grow.offset((0) as isize)) = 1; - (*grow.offset((1) as isize)) = 2; - grow = (libc::realloc( - (grow as *mut i32 as *mut ::libc::c_void), - (4_u64).wrapping_mul(::std::mem::size_of::() as u64 as u64) as ::libc::size_t, - ) as *mut i32); - (*grow.offset((2) as isize)) = 3; - (*grow.offset((3) as isize)) = 4; - assert!(((((*grow.offset((0) as isize)) == (1)) as i32) != 0)); - assert!(((((*grow.offset((1) as isize)) == (2)) as i32) != 0)); - assert!(((((*grow.offset((2) as isize)) == (3)) as i32) != 0)); - assert!(((((*grow.offset((3) as isize)) == (4)) as i32) != 0)); - libc::free((grow as *mut i32 as *mut ::libc::c_void)); - let mut zeros: *mut i32 = (libc::calloc( - 4_u64 as ::libc::size_t, - ::std::mem::size_of::() as u64 as ::libc::size_t, - ) as *mut i32); - let mut i: i32 = 0; - 'loop_: while ((((i) < (4)) as i32) != 0) { - assert!(((((*zeros.offset((i) as isize)) == (0)) as i32) != 0)); - i.postfix_inc(); + let mut pmalloc: Option *mut ::libc::c_void> = Some(libcc2rs::malloc_unsafe); + let mut pfree: Option = Some(libcc2rs::free_unsafe); + let mut prealloc: Option *mut ::libc::c_void> = + Some(libcc2rs::realloc_unsafe); + let mut pcalloc: Option *mut ::libc::c_void> = + Some(libcc2rs::calloc_unsafe); + 'loop_: loop { + let mut p: *mut i32 = ((unsafe { + let _arg0: u64 = ::std::mem::size_of::() as u64; + (pmalloc).unwrap()(_arg0) + }) as *mut i32); + (*p) = 42; + assert!(((((*p) == (42)) as i32) != 0)); + (unsafe { + let _arg0: *mut ::libc::c_void = (p as *mut i32 as *mut ::libc::c_void); + (pfree).unwrap()(_arg0) + }); + let mut arr: *mut i32 = ((unsafe { + let _arg0: u64 = (4_u64).wrapping_mul(::std::mem::size_of::() as u64 as u64); + (pmalloc).unwrap()(_arg0) + }) as *mut i32); + let mut i: i32 = 0; + 'loop_: while ((((i) < (4)) as i32) != 0) { + (*arr.offset((i) as isize)) = ((i) * (10)); + i.postfix_inc(); + } + assert!(((((*arr.offset((0) as isize)) == (0)) as i32) != 0)); + assert!(((((*arr.offset((3) as isize)) == (30)) as i32) != 0)); + (unsafe { + let _arg0: *mut ::libc::c_void = (arr as *mut i32 as *mut ::libc::c_void); + (pfree).unwrap()(_arg0) + }); + let mut grow: *mut i32 = ((unsafe { + let _arg0: u64 = (2_u64).wrapping_mul(::std::mem::size_of::() as u64 as u64); + (pmalloc).unwrap()(_arg0) + }) as *mut i32); + (*grow.offset((0) as isize)) = 1; + (*grow.offset((1) as isize)) = 2; + grow = ((unsafe { + let _arg0: *mut ::libc::c_void = (grow as *mut i32 as *mut ::libc::c_void); + let _arg1: u64 = (4_u64).wrapping_mul(::std::mem::size_of::() as u64 as u64); + (prealloc).unwrap()(_arg0, _arg1) + }) as *mut i32); + (*grow.offset((2) as isize)) = 3; + (*grow.offset((3) as isize)) = 4; + assert!(((((*grow.offset((0) as isize)) == (1)) as i32) != 0)); + assert!(((((*grow.offset((1) as isize)) == (2)) as i32) != 0)); + assert!(((((*grow.offset((2) as isize)) == (3)) as i32) != 0)); + assert!(((((*grow.offset((3) as isize)) == (4)) as i32) != 0)); + (unsafe { + let _arg0: *mut ::libc::c_void = (grow as *mut i32 as *mut ::libc::c_void); + (pfree).unwrap()(_arg0) + }); + let mut zeros: *mut i32 = ((unsafe { + let _arg0: u64 = 4_u64; + let _arg1: u64 = ::std::mem::size_of::() as u64; + (pcalloc).unwrap()(_arg0, _arg1) + }) as *mut i32); + let mut i: i32 = 0; + 'loop_: while ((((i) < (4)) as i32) != 0) { + assert!(((((*zeros.offset((i) as isize)) == (0)) as i32) != 0)); + i.postfix_inc(); + } + (unsafe { + let _arg0: *mut ::libc::c_void = (zeros as *mut i32 as *mut ::libc::c_void); + (pfree).unwrap()(_arg0) + }); + if !(0 != 0) { + break; + } } - libc::free((zeros as *mut i32 as *mut ::libc::c_void)); return 0; } diff --git a/tests/unit/out/unsafe/string_h.rs b/tests/unit/out/unsafe/string_h.rs index 1efd249..077304d 100644 --- a/tests/unit/out/unsafe/string_h.rs +++ b/tests/unit/out/unsafe/string_h.rs @@ -338,8 +338,7 @@ pub unsafe fn test_strrchr_9() { ); } pub unsafe fn test_strdup_10() { - let mut d: *mut u8 = - libc::strdup((b"hello\0".as_ptr().cast_mut()).cast_const() as *const i8) as *mut u8; + let mut d: *mut u8 = libcc2rs::strdup_unsafe((b"hello\0".as_ptr().cast_mut()).cast_const()); assert!((((!((d).is_null())) as i32) != 0)); assert!( ((((libc::strcmp( @@ -348,7 +347,7 @@ pub unsafe fn test_strdup_10() { )) == (0)) as i32) != 0) ); - libc::free((d as *mut u8 as *mut ::libc::c_void)); + libcc2rs::free_unsafe((d as *mut u8 as *mut ::libc::c_void)); let mut p: *const u8 = (b"world\0".as_ptr().cast_mut()).cast_const(); let mut buf: [u8; 4] = [ (('a' as i32) as u8), @@ -356,13 +355,13 @@ pub unsafe fn test_strdup_10() { (('c' as i32) as u8), (('\0' as i32) as u8), ]; - let mut d2: *mut u8 = libc::strdup(p as *const i8) as *mut u8; + let mut d2: *mut u8 = libcc2rs::strdup_unsafe(p); assert!((((!((d2).is_null())) as i32) != 0)); assert!( ((((libc::strcmp((d2).cast_const() as *const i8, p as *const i8)) == (0)) as i32) != 0) ); - libc::free((d2 as *mut u8 as *mut ::libc::c_void)); - let mut d3: *mut u8 = libc::strdup((buf.as_mut_ptr()).cast_const() as *const i8) as *mut u8; + libcc2rs::free_unsafe((d2 as *mut u8 as *mut ::libc::c_void)); + let mut d3: *mut u8 = libcc2rs::strdup_unsafe((buf.as_mut_ptr()).cast_const()); assert!((((!((d3).is_null())) as i32) != 0)); assert!( ((((libc::strcmp( @@ -371,7 +370,7 @@ pub unsafe fn test_strdup_10() { )) == (0)) as i32) != 0) ); - libc::free((d3 as *mut u8 as *mut ::libc::c_void)); + libcc2rs::free_unsafe((d3 as *mut u8 as *mut ::libc::c_void)); } pub unsafe fn test_strcspn_11() { assert!(