Skip to content

Commit 7374e08

Browse files
committed
Add malloc/calloc/free implementations
1 parent bc44ab5 commit 7374e08

3 files changed

Lines changed: 69 additions & 29 deletions

File tree

libcc2rs/src/alloc.rs

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,36 @@
33

44
use crate::rc::{AnyPtr, Ptr};
55

6-
pub fn malloc_refcount(_a0: usize) -> AnyPtr {
7-
todo!("malloc_refcount")
6+
pub fn malloc_refcount(a0: usize) -> AnyPtr {
7+
Ptr::alloc_array(vec![0u8; a0].into_boxed_slice()).to_any()
88
}
99

10-
pub fn free_refcount(_a0: AnyPtr) {
11-
todo!("free_refcount")
10+
pub fn free_refcount(a0: AnyPtr) {
11+
if a0.is_null() {
12+
return;
13+
}
14+
a0.reinterpret_cast::<u8>().delete_array();
1215
}
1316

14-
pub fn realloc_refcount(_a0: AnyPtr, _a1: usize) -> AnyPtr {
15-
todo!("realloc_refcount")
17+
pub fn realloc_refcount(a0: AnyPtr, a1: usize) -> AnyPtr {
18+
if a0.is_null() {
19+
return malloc_refcount(a1);
20+
}
21+
let __new = Ptr::alloc_array(vec![0u8; a1].into_boxed_slice()).to_any();
22+
let __n = a1.min(a0.reinterpret_cast::<u8>().len());
23+
__new.memcpy(&a0, __n);
24+
a0.reinterpret_cast::<u8>().delete_array();
25+
__new
1626
}
1727

18-
pub fn calloc_refcount(_a0: usize, _a1: usize) -> AnyPtr {
19-
todo!("calloc_refcount")
28+
pub fn calloc_refcount(a0: usize, a1: usize) -> AnyPtr {
29+
Ptr::alloc_array(vec![0u8; a0.wrapping_mul(a1)].into_boxed_slice()).to_any()
2030
}
2131

22-
pub fn strdup_refcount(_a0: Ptr<u8>) -> Ptr<u8> {
23-
todo!("strdup_refcount")
32+
pub fn strdup_refcount(a0: Ptr<u8>) -> Ptr<u8> {
33+
let mut bytes: Vec<u8> = a0.to_c_string_iterator().collect();
34+
bytes.push(0);
35+
Ptr::alloc_array(bytes.into_boxed_slice())
2436
}
2537

2638
/// # Safety

libcc2rs/src/rc.rs

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -210,32 +210,38 @@ impl<T> Ptr<T> {
210210

211211
#[inline]
212212
pub fn delete(&self) {
213-
assert_eq!(self.offset, 0, "ub: invalid delete");
214-
let weak = match self.kind {
215-
PtrKind::HeapSingle(ref weak) => weak,
213+
match &self.kind {
214+
PtrKind::HeapSingle(weak) => {
215+
assert_eq!(self.offset, 0, "ub: invalid delete");
216+
assert_eq!(Weak::strong_count(weak), 1, "ub: invalid delete");
217+
unsafe {
218+
let strong = weak.upgrade().expect("ub: dangling pointer");
219+
Rc::from_raw(Rc::as_ptr(&strong));
220+
}
221+
assert_eq!(Weak::strong_count(weak), 0, "ub: double free");
222+
}
223+
PtrKind::Reinterpreted(data) => data.alloc.delete(),
224+
PtrKind::Null => {}
216225
_ => panic!("ub: invalid delete"),
217-
};
218-
assert_eq!(Weak::strong_count(weak), 1, "ub: invalid delete");
219-
unsafe {
220-
let strong = weak.upgrade().expect("ub: dangling pointer");
221-
Rc::from_raw(Rc::as_ptr(&strong));
222226
}
223-
assert_eq!(Weak::strong_count(weak), 0, "ub: strong count is not zero");
224227
}
225228

226229
#[inline]
227230
pub fn delete_array(&self) {
228-
assert_eq!(self.offset, 0, "ub: invalid delete");
229-
let weak = match self.kind {
230-
PtrKind::HeapArray(ref weak) => weak,
231+
match &self.kind {
232+
PtrKind::HeapArray(weak) => {
233+
assert_eq!(self.offset, 0, "ub: invalid delete");
234+
assert_eq!(Weak::strong_count(weak), 1, "ub: invalid delete");
235+
unsafe {
236+
let strong = weak.upgrade().expect("ub: dangling pointer");
237+
Rc::from_raw(Rc::as_ptr(&strong));
238+
}
239+
assert_eq!(Weak::strong_count(weak), 0, "ub: double free");
240+
}
241+
PtrKind::Reinterpreted(data) => data.alloc.delete(),
242+
PtrKind::Null => {}
231243
_ => panic!("ub: invalid delete"),
232-
};
233-
assert_eq!(Weak::strong_count(weak), 1, "ub: invalid delete");
234-
unsafe {
235-
let strong = weak.upgrade().expect("ub: dangling pointer");
236-
Rc::from_raw(Rc::as_ptr(&strong));
237244
}
238-
assert_eq!(Weak::strong_count(weak), 0, "ub: strong count is not zero");
239245
}
240246

241247
#[inline]

libcc2rs/src/reinterpret.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
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, rc::Weak};
4+
use std::{
5+
cell::RefCell,
6+
rc::{Rc, Weak},
7+
};
58

69
pub trait ByteRepr: 'static {
710
fn byte_size() -> usize
@@ -100,6 +103,7 @@ pub trait OriginalAlloc {
100103
fn total_byte_len(&self) -> usize;
101104
// Stable address used for pointer equality across PtrKind variants.
102105
fn address(&self) -> usize;
106+
fn delete(&self);
103107
}
104108

105109
// Read bytes starting at `byte_offset` from a slice of S elements into `buf`.
@@ -165,6 +169,15 @@ impl<T: ByteRepr> OriginalAlloc for SingleOriginalAlloc<T> {
165169
fn address(&self) -> usize {
166170
self.weak.as_ptr() as usize
167171
}
172+
173+
fn delete(&self) {
174+
assert_eq!(Weak::strong_count(&self.weak), 1, "ub: invalid delete");
175+
unsafe {
176+
let strong = self.weak.upgrade().expect("ub: dangling pointer");
177+
Rc::from_raw(Rc::as_ptr(&strong));
178+
}
179+
assert_eq!(Weak::strong_count(&self.weak), 0, "ub: double free");
180+
}
168181
}
169182

170183
pub(crate) trait AsSlice {
@@ -219,4 +232,13 @@ impl<T: AsSlice + 'static> OriginalAlloc for SliceOriginalAlloc<T> {
219232
fn address(&self) -> usize {
220233
self.weak.as_ptr() as usize
221234
}
235+
236+
fn delete(&self) {
237+
assert_eq!(Weak::strong_count(&self.weak), 1, "ub: invalid delete");
238+
unsafe {
239+
let strong = self.weak.upgrade().expect("ub: dangling pointer");
240+
Rc::from_raw(Rc::as_ptr(&strong));
241+
}
242+
assert_eq!(Weak::strong_count(&self.weak), 0, "ub: double free");
243+
}
222244
}

0 commit comments

Comments
 (0)