Skip to content

Commit b3ff64c

Browse files
committed
Remove 'hl' prefix from hlmalloc/hlfree/hlcalling/hlfree and update documentations, and mark the functions unsafe
Signed-off-by: Ludvig Liljenberg <[email protected]>
1 parent 9f2e102 commit b3ff64c

File tree

5 files changed

+85
-35
lines changed

5 files changed

+85
-35
lines changed

src/hyperlight_guest/build.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -133,11 +133,6 @@ fn cargo_main() {
133133
cfg.define("__x86_64__", None);
134134
cfg.define("__LITTLE_ENDIAN__", None);
135135

136-
cfg.define("malloc", "hlmalloc");
137-
cfg.define("calloc", "hlcalloc");
138-
cfg.define("free", "hlfree");
139-
cfg.define("realloc", "hlrealloc");
140-
141136
// silence compiler warnings
142137
cfg.flag("-Wno-sign-compare");
143138
cfg.flag("-Wno-bitwise-op-parentheses");

src/hyperlight_guest/src/memory.rs

Lines changed: 72 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,42 @@ use crate::entrypoint::abort_with_code;
2525

2626
extern crate alloc;
2727

28-
#[no_mangle]
29-
pub extern "C" fn hlmalloc(size: usize) -> *mut c_void {
30-
alloc_helper(size, false)
31-
}
28+
/*
29+
C-wrappers for Rust's registered global allocator.
3230
33-
pub fn alloc_helper(size: usize, zero: bool) -> *mut c_void {
34-
// Allocate a block that includes space for both layout information and data
31+
Each memory allocation via `malloc/calloc/realloc` is stored together with a `alloc::Layout` describing
32+
the size and alignment of the allocation. This layout is stored just before the actual raw memory returned to the caller.
33+
34+
Example: A call to malloc(64) will allocate space for both an `alloc::Layout` and 64 bytes of memory:
35+
36+
----------------------------------------------------------------------------------------
37+
| Layout { size: 64 + size_of::<Layout>(), ... } | 64 bytes of memory | ...
38+
----------------------------------------------------------------------------------------
39+
^
40+
|
41+
|
42+
ptr returned to caller
43+
*/
44+
45+
// We assume the maximum alignment for any value is the alignment of u128.
46+
const MAX_ALIGN: usize = align_of::<u128>();
47+
48+
/// Allocates a block of memory with the given size. The memory is only guaranteed to be initialized to 0s if `zero` is true, otherwise
49+
/// it may or may not be initialized.
50+
///
51+
/// # Safety
52+
/// The returned pointer must be freed with `memory::free` when it is no longer needed, otherwise memory will leak.
53+
unsafe fn alloc_helper(size: usize, zero: bool) -> *mut c_void {
3554
if size == 0 {
3655
return ptr::null_mut();
3756
}
3857

39-
let total_size = size + size_of::<Layout>();
40-
let layout = Layout::from_size_align(total_size, align_of::<usize>()).unwrap();
58+
// Allocate a block that includes space for both layout information and data
59+
let total_size = size
60+
.checked_add(size_of::<Layout>())
61+
.expect("data and layout size should not overflow in alloc");
62+
let layout = Layout::from_size_align(total_size, MAX_ALIGN).expect("Invalid layout");
63+
4164
unsafe {
4265
let raw_ptr = match zero {
4366
true => alloc::alloc::alloc_zeroed(layout),
@@ -53,14 +76,36 @@ pub fn alloc_helper(size: usize, zero: bool) -> *mut c_void {
5376
}
5477
}
5578

79+
/// Allocates a block of memory with the given size.
80+
/// The memory is not guaranteed to be initialized to 0s.
81+
///
82+
/// # Safety
83+
/// The returned pointer must be freed with `memory::free` when it is no longer needed, otherwise memory will leak.
84+
#[no_mangle]
85+
pub unsafe extern "C" fn malloc(size: usize) -> *mut c_void {
86+
alloc_helper(size, false)
87+
}
88+
89+
/// Allocates a block of memory for an array of `nmemb` elements, each of `size` bytes.
90+
/// The memory is initialized to 0s.
91+
///
92+
/// # Safety
93+
/// The returned pointer must be freed with `memory::free` when it is no longer needed, otherwise memory will leak.
5694
#[no_mangle]
57-
pub extern "C" fn hlcalloc(n: usize, size: usize) -> *mut c_void {
58-
let total_size = n * size;
95+
pub unsafe extern "C" fn calloc(nmemb: usize, size: usize) -> *mut c_void {
96+
let total_size = nmemb
97+
.checked_mul(size)
98+
.expect("nmemb * size should not overflow in calloc");
99+
59100
alloc_helper(total_size, true)
60101
}
61102

103+
/// Frees the memory block pointed to by `ptr`.
104+
///
105+
/// # Safety
106+
/// `ptr` must be a pointer to a memory block previously allocated by `memory::malloc`, `memory::calloc`, or `memory::realloc`.
62107
#[no_mangle]
63-
pub extern "C" fn hlfree(ptr: *mut c_void) {
108+
pub unsafe extern "C" fn free(ptr: *mut c_void) {
64109
if !ptr.is_null() {
65110
unsafe {
66111
let block_start = (ptr as *const Layout).sub(1);
@@ -70,11 +115,22 @@ pub extern "C" fn hlfree(ptr: *mut c_void) {
70115
}
71116
}
72117

118+
/// Changes the size of the memory block pointed to by `ptr` to `size` bytes. If the returned ptr is non-null,
119+
/// any usage of the old memory block is immediately undefined behavior.
120+
///
121+
/// # Safety
122+
/// `ptr` must be a pointer to a memory block previously allocated by `memory::malloc`, `memory::calloc`, or `memory::realloc`.
73123
#[no_mangle]
74-
pub extern "C" fn hlrealloc(ptr: *mut c_void, size: usize) -> *mut c_void {
124+
pub unsafe extern "C" fn realloc(ptr: *mut c_void, size: usize) -> *mut c_void {
75125
if ptr.is_null() {
76126
// If the pointer is null, treat as a malloc
77-
return hlmalloc(size);
127+
return malloc(size);
128+
}
129+
130+
if size == 0 {
131+
// If the size is 0, treat as a free and return null
132+
free(ptr);
133+
return ptr::null_mut();
78134
}
79135

80136
unsafe {
@@ -84,10 +140,11 @@ pub extern "C" fn hlrealloc(ptr: *mut c_void, size: usize) -> *mut c_void {
84140

85141
let block_start = (ptr as *const Layout).sub(1);
86142
let old_layout = block_start.read();
87-
let new_layout = Layout::from_size_align(total_new_size, align_of::<usize>()).unwrap();
143+
let new_layout = Layout::from_size_align(total_new_size, MAX_ALIGN).unwrap();
88144

89145
let new_block_start =
90-
alloc::alloc::realloc(block_start as *mut u8, layout, total_new_size) as *mut Layout;
146+
alloc::alloc::realloc(block_start as *mut u8, old_layout, total_new_size)
147+
as *mut Layout;
91148

92149
if new_block_start.is_null() {
93150
// Realloc failed

src/hyperlight_host/tests/integration_test.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -186,14 +186,14 @@ fn guest_panic() {
186186
}
187187

188188
#[test]
189-
fn guest_hlmalloc() {
189+
fn guest_malloc() {
190190
// this test is rust-only
191191
let sbox1: SingleUseSandbox = new_uninit_rust().unwrap().evolve(Noop::default()).unwrap();
192192

193193
let size_to_allocate = 2000;
194194
let res = sbox1
195195
.call_guest_function_by_name(
196-
"TestHlMalloc", // uses hlmalloc
196+
"TestMalloc",
197197
ReturnType::Int,
198198
Some(vec![ParameterValue::Int(size_to_allocate)]),
199199
)
@@ -202,7 +202,7 @@ fn guest_hlmalloc() {
202202
}
203203

204204
#[test]
205-
fn guest_malloc() {
205+
fn guest_allocate_vec() {
206206
let sbox1: SingleUseSandbox = new_uninit().unwrap().evolve(Noop::default()).unwrap();
207207

208208
let size_to_allocate = 2000;
@@ -220,14 +220,14 @@ fn guest_malloc() {
220220

221221
// checks that malloc failures are captured correctly
222222
#[test]
223-
fn guest_hlmalloc_abort() {
223+
fn guest_malloc_abort() {
224224
let sbox1: SingleUseSandbox = new_uninit_rust().unwrap().evolve(Noop::default()).unwrap();
225225

226226
let size = 20000000; // some big number that should fail when allocated
227227

228228
let res = sbox1
229229
.call_guest_function_by_name(
230-
"TestHlMalloc",
230+
"TestMalloc",
231231
ReturnType::Int,
232232
Some(vec![ParameterValue::Int(size)]),
233233
)

src/tests/c_guests/c_simpleguest/main.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ double echo_double(double d) { return d; }
1919

2020
hl_Vec *set_byte_array_to_zero(const hl_FunctionCall* params) {
2121
hl_Vec input = params->parameters[0].value.VecBytes;
22-
uint8_t *x = hlmalloc(input.len);
22+
uint8_t *x = malloc(input.len);
2323
for (uintptr_t i = 0; i < input.len; i++) {
2424
x[i] = 0;
2525
}
@@ -90,7 +90,7 @@ int small_var(void) {
9090
}
9191

9292
int call_malloc(int32_t size) {
93-
void *heap_memory = hlmalloc(size);
93+
void *heap_memory = malloc(size);
9494
if (NULL == heap_memory) {
9595
hl_set_error(hl_ErrorCode_GuestError, "Malloc Failed");
9696
}
@@ -99,12 +99,12 @@ int call_malloc(int32_t size) {
9999
}
100100

101101
int malloc_and_free(int32_t size) {
102-
void *heap_memory = hlmalloc(size);
102+
void *heap_memory = malloc(size);
103103
if (NULL == heap_memory) {
104104
hl_set_error(hl_ErrorCode_GuestError, "Malloc Failed");
105105
}
106106

107-
hlfree(heap_memory);
107+
free(heap_memory);
108108

109109
return size;
110110
}

src/tests/rust_guests/simpleguest/src/main.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ use hyperlight_guest::guest_function_register::register_function;
5454
use hyperlight_guest::host_function_call::{
5555
call_host_function, get_host_value_return_as_int, get_host_value_return_as_ulong,
5656
};
57-
use hyperlight_guest::memory::hlmalloc;
57+
use hyperlight_guest::memory::malloc;
5858
use hyperlight_guest::{logging, MIN_STACK_ADDRESS};
5959
use log::{error, LevelFilter};
6060

@@ -623,11 +623,9 @@ fn execute_on_heap(_function_call: &FunctionCall) -> Result<Vec<u8>> {
623623
Ok(get_flatbuffer_result_from_string("fail"))
624624
}
625625

626-
#[no_mangle]
627-
#[allow(improper_ctypes_definitions)]
628-
pub extern "C" fn test_rust_malloc(function_call: &FunctionCall) -> Result<Vec<u8>> {
626+
fn test_rust_malloc(function_call: &FunctionCall) -> Result<Vec<u8>> {
629627
if let ParameterValue::Int(code) = function_call.parameters.clone().unwrap()[0].clone() {
630-
let ptr = hlmalloc(code as usize);
628+
let ptr = unsafe { malloc(code as usize) };
631629
Ok(get_flatbuffer_result_from_int(ptr as i32))
632630
} else {
633631
Err(HyperlightGuestError::new(
@@ -1012,7 +1010,7 @@ pub extern "C" fn hyperlight_main() {
10121010
register_function(guest_panic_def);
10131011

10141012
let rust_malloc_def = GuestFunctionDefinition::new(
1015-
"TestHlMalloc".to_string(),
1013+
"TestMalloc".to_string(),
10161014
Vec::from(&[ParameterType::Int]),
10171015
ReturnType::Int,
10181016
test_rust_malloc as i64,

0 commit comments

Comments
 (0)