Allocate PropList description with memory::alloc_bytes.

All memory allocations passed back from FFI functions should be allocated with
`memory::alloc_bytes`, so that C code can call `memory::free_bytes` when it's
done with them.
This commit is contained in:
2025-10-23 14:46:56 -04:00
parent cf588d6e27
commit 12930739ec
2 changed files with 40 additions and 5 deletions
+19 -3
View File
@@ -18,7 +18,7 @@
//! memory than the baseline Window Maker code, it isn't really necessary in
//! this day and age.
use std::{alloc, mem, ptr::{self, NonNull}};
use std::{alloc, ffi::{c_char, CStr}, mem, ptr::{self, NonNull}};
/// Tracks the layout and reference count of an allocated chunk of memory.
#[derive(Clone, Copy)]
@@ -84,6 +84,14 @@ pub fn alloc_bytes(size: usize) -> *mut u8 {
result
}
/// Allocates a segment with [`alloc_bytes`] and fills it with the contents of
/// `s`. The resulting string should be free'd by passing it to [`free_bytes`].
pub fn alloc_string(s: &CStr) -> *mut c_char {
let result = alloc_bytes(s.count_bytes() + 1).cast::<c_char>();
unsafe { ptr::copy(s.as_ptr().cast::<c_char>(), result, s.count_bytes() + 1); }
result.cast::<c_char>()
}
/// Frees the bytes pointed to by `b`.
///
/// ## Safety
@@ -170,9 +178,9 @@ pub mod ffi {
#[cfg(test)]
mod test {
use super::{alloc_bytes, free_bytes, ffi::wrealloc, Header};
use super::{alloc_bytes, alloc_string, ffi::wrealloc, free_bytes, Header};
use std::{mem, os::raw::c_void, ptr};
use std::{ffi::CStr, mem, os::raw::c_void, ptr};
#[test]
fn recover_header() {
@@ -219,4 +227,12 @@ mod test {
assert_eq!(unsafe { *y }, 17);
unsafe { free_bytes(y.cast::<u8>()); }
}
#[test]
fn alloc_free_string() {
let s = alloc_string(c"hello");
assert!(!s.is_null());
assert_eq!(unsafe { CStr::from_ptr(s) }, c"hello");
unsafe { free_bytes(s.cast::<u8>()); }
}
}
+21 -2
View File
@@ -357,7 +357,7 @@ impl PropList {
}
pub mod ffi {
use crate::{data::Data, find_file::path_from_cstr};
use crate::{data::Data, find_file::path_from_cstr, memory};
use super::{
merge_deep, merge_shallow, parser, subtract_deep, subtract_shallow, Node, PropList,
@@ -784,7 +784,7 @@ pub mod ffi {
}
}
match CString::new(buf) {
Ok(s) => s.into_raw(),
Ok(s) => memory::alloc_string(s.as_c_str()),
Err(_) => ptr::null_mut(),
}
}
@@ -869,3 +869,22 @@ pub mod ffi {
}
}
}
#[cfg(test)]
mod test {
use std::ffi::CString;
use crate::memory;
use super::{Node, PropList, ffi};
#[test]
fn free_proplist_description() {
let mut plist = PropList::new(Node::Array(vec![PropList::new(Node::String(CString::from(c"hello"))),
PropList::new(Node::String(CString::from(c"world!")))]));
let desc = unsafe { ffi::WMGetPropListDescription(&mut plist, 1) };
assert!(!desc.is_null());
unsafe { memory::ffi::wfree(desc.cast()); }
}
}