Skip to content

Commit 5a0cdcd

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

File tree

4 files changed

+86
-8
lines changed

4 files changed

+86
-8
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: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -204,11 +204,11 @@ pub type __uid_t = ::std::os::raw::c_uint;
204204
pub type __gid_t = ::std::os::raw::c_uint;
205205
pub type __ino_t = ::std::os::raw::c_ulong;
206206
pub type __mode_t = ::std::os::raw::c_uint;
207-
pub type __nlink_t = ::std::os::raw::c_ulong;
207+
pub type __nlink_t = ::std::os::raw::c_uint;
208208
pub type __off_t = ::std::os::raw::c_long;
209209
pub type __off64_t = ::std::os::raw::c_long;
210210
pub type __time_t = ::std::os::raw::c_long;
211-
pub type __blksize_t = ::std::os::raw::c_long;
211+
pub type __blksize_t = ::std::os::raw::c_int;
212212
pub type __blkcnt_t = ::std::os::raw::c_long;
213213
pub type __syscall_slong_t = ::std::os::raw::c_long;
214214
pub type gid_t = __gid_t;
@@ -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
}
@@ -768,19 +777,20 @@ pub type zend_class_arrayaccess_funcs = _zend_class_arrayaccess_funcs;
768777
pub struct stat {
769778
pub st_dev: __dev_t,
770779
pub st_ino: __ino_t,
771-
pub st_nlink: __nlink_t,
772780
pub st_mode: __mode_t,
781+
pub st_nlink: __nlink_t,
773782
pub st_uid: __uid_t,
774783
pub st_gid: __gid_t,
775-
pub __pad0: ::std::os::raw::c_int,
776784
pub st_rdev: __dev_t,
785+
pub __pad1: __dev_t,
777786
pub st_size: __off_t,
778787
pub st_blksize: __blksize_t,
788+
pub __pad2: ::std::os::raw::c_int,
779789
pub st_blocks: __blkcnt_t,
780790
pub st_atim: timespec,
781791
pub st_mtim: timespec,
782792
pub st_ctim: timespec,
783-
pub __glibc_reserved: [__syscall_slong_t; 3usize],
793+
pub __glibc_reserved: [::std::os::raw::c_int; 2usize],
784794
}
785795
pub type zend_stream_fsizer_t =
786796
::std::option::Option<unsafe extern "C" fn(handle: *mut ::std::os::raw::c_void) -> usize>;
@@ -1420,7 +1430,7 @@ pub struct _zend_execute_data {
14201430
pub run_time_cache: *mut *mut ::std::os::raw::c_void,
14211431
pub extra_named_params: *mut zend_array,
14221432
}
1423-
pub type __jmp_buf = [::std::os::raw::c_long; 8usize];
1433+
pub type __jmp_buf = [::std::os::raw::c_ulonglong; 22usize];
14241434
#[repr(C)]
14251435
#[derive(Debug, Copy, Clone)]
14261436
pub struct __jmp_buf_tag {

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(|| {

0 commit comments

Comments
 (0)