Skip to content

Commit 5e8c374

Browse files
committed
feat(alloc): add estrdup
1 parent f4fd27e commit 5e8c374

File tree

5 files changed

+80
-2
lines changed

5 files changed

+80
-2
lines changed

allowed_bindings.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ bind! {
2727
_call_user_function_impl,
2828
_efree,
2929
_emalloc,
30+
_estrdup,
3031
_zend_executor_globals,
3132
_sapi_globals_struct,
3233
_sapi_module_struct,

docsrs_bindings.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,15 @@ extern "C" {
490490
__zend_orig_lineno: u32,
491491
);
492492
}
493+
extern "C" {
494+
pub fn _estrdup(
495+
s: *const ::std::os::raw::c_char,
496+
__zend_filename: *const ::std::os::raw::c_char,
497+
__zend_lineno: u32,
498+
__zend_orig_filename: *const ::std::os::raw::c_char,
499+
__zend_orig_lineno: u32,
500+
) -> *mut ::std::os::raw::c_char;
501+
}
493502
extern "C" {
494503
pub fn __zend_malloc(len: usize) -> *mut ::std::os::raw::c_void;
495504
}

src/alloc.rs

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@
33
44
use cfg_if::cfg_if;
55

6-
use crate::ffi::{_efree, _emalloc};
7-
use std::{alloc::Layout, ffi::c_void};
6+
use crate::ffi::{_efree, _emalloc, _estrdup};
7+
use std::{
8+
alloc::Layout,
9+
ffi::{c_char, c_void, CString},
10+
};
811

912
/// Uses the PHP memory allocator to allocate request-bound memory.
1013
///
@@ -62,3 +65,66 @@ pub unsafe fn efree(ptr: *mut u8) {
6265
}
6366
}
6467
}
68+
69+
/// Duplicates a string using the PHP memory manager.
70+
///
71+
/// # Parameters
72+
///
73+
/// * `string` - The string to duplicate, which can be any type that can be
74+
/// converted into a `Vec<u8>`.
75+
///
76+
/// # Returns
77+
///
78+
/// A pointer to the duplicated string in the PHP memory manager.
79+
pub fn estrdup(string: impl Into<Vec<u8>>) -> *mut c_char {
80+
let string = unsafe { CString::from_vec_unchecked(string.into()) }.into_raw();
81+
82+
let result = unsafe {
83+
#[cfg(php_debug)]
84+
{
85+
_estrdup(string, std::ptr::null_mut(), 0, std::ptr::null_mut(), 0)
86+
}
87+
#[cfg(not(php_debug))]
88+
{
89+
_estrdup(string)
90+
}
91+
};
92+
93+
drop(unsafe { CString::from_raw(string) });
94+
result
95+
}
96+
97+
#[cfg(test)]
98+
#[cfg(feature = "embed")]
99+
mod test {
100+
use super::*;
101+
use crate::embed::Embed;
102+
use std::ffi::CStr;
103+
104+
#[test]
105+
fn test_emalloc() {
106+
Embed::run(|| {
107+
let layout = Layout::from_size_align(16, 8).expect("should create layout");
108+
let ptr = emalloc(layout);
109+
assert!(!ptr.is_null());
110+
unsafe { efree(ptr) };
111+
});
112+
}
113+
114+
#[test]
115+
fn test_estrdup() {
116+
Embed::run(|| {
117+
let original = "Hello, world!";
118+
let duplicated = estrdup(original);
119+
assert!(!duplicated.is_null());
120+
121+
let duplicated_str = unsafe { CStr::from_ptr(duplicated) };
122+
assert_eq!(
123+
duplicated_str.to_str().expect("should convert to str"),
124+
original
125+
);
126+
127+
unsafe { efree(duplicated.cast::<u8>()) }
128+
});
129+
}
130+
}

src/exception.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,7 @@ mod tests {
342342
});
343343
}
344344

345+
#[cfg(feature = "anyhow")]
345346
#[test]
346347
fn test_from_anyhow() {
347348
Embed::run(|| {

tools/update_bindings.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
set -e
77

88
docker buildx build \
9+
--platform linux/amd64 \
910
--target docsrs_bindings \
1011
-o type=local,dest=. \
1112
--build-arg PHP_VERSION=8.3 \

0 commit comments

Comments
 (0)