Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions allowed_bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ bind! {
_emalloc,
_zend_executor_globals,
_sapi_globals_struct,
_sapi_module_struct,
_zend_expected_type,
_zend_expected_type_Z_EXPECTED_ARRAY,
_zend_expected_type_Z_EXPECTED_BOOL,
Expand Down Expand Up @@ -243,6 +244,7 @@ bind! {
zend_class_unserialize_deny,
zend_executor_globals,
sapi_globals_struct,
sapi_module_struct,
zend_objects_store_del,
zend_hash_move_forward_ex,
zend_hash_get_current_key_type_ex,
Expand All @@ -254,6 +256,7 @@ bind! {
ZEND_ACC_NOT_SERIALIZABLE,
executor_globals,
sapi_globals,
sapi_module,
php_printf,
__zend_malloc,
tsrm_get_ls_cache,
Expand Down
117 changes: 117 additions & 0 deletions docsrs_bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,8 @@ pub type __time_t = ::std::os::raw::c_long;
pub type __blksize_t = ::std::os::raw::c_long;
pub type __blkcnt_t = ::std::os::raw::c_long;
pub type __syscall_slong_t = ::std::os::raw::c_long;
pub type gid_t = __gid_t;
pub type uid_t = __uid_t;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct __sigset_t {
Expand Down Expand Up @@ -2265,6 +2267,12 @@ extern "C" {
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct sapi_header_struct {
pub header: *mut ::std::os::raw::c_char,
pub header_len: usize,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct sapi_headers_struct {
pub headers: zend_llist,
pub http_response_code: ::std::os::raw::c_int,
Expand All @@ -2273,6 +2281,10 @@ pub struct sapi_headers_struct {
pub http_status_line: *mut ::std::os::raw::c_char,
}
pub type sapi_post_entry = _sapi_post_entry;
pub type sapi_module_struct = _sapi_module_struct;
extern "C" {
pub static mut sapi_module: sapi_module_struct;
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct sapi_request_info {
Expand Down Expand Up @@ -2323,6 +2335,111 @@ pub type sapi_globals_struct = _sapi_globals_struct;
extern "C" {
pub static mut sapi_globals: sapi_globals_struct;
}
pub const sapi_header_op_enum_SAPI_HEADER_REPLACE: sapi_header_op_enum = 0;
pub const sapi_header_op_enum_SAPI_HEADER_ADD: sapi_header_op_enum = 1;
pub const sapi_header_op_enum_SAPI_HEADER_DELETE: sapi_header_op_enum = 2;
pub const sapi_header_op_enum_SAPI_HEADER_DELETE_ALL: sapi_header_op_enum = 3;
pub const sapi_header_op_enum_SAPI_HEADER_SET_STATUS: sapi_header_op_enum = 4;
pub type sapi_header_op_enum = ::std::os::raw::c_uint;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct _sapi_module_struct {
pub name: *mut ::std::os::raw::c_char,
pub pretty_name: *mut ::std::os::raw::c_char,
pub startup: ::std::option::Option<
unsafe extern "C" fn(sapi_module: *mut _sapi_module_struct) -> ::std::os::raw::c_int,
>,
pub shutdown: ::std::option::Option<
unsafe extern "C" fn(sapi_module: *mut _sapi_module_struct) -> ::std::os::raw::c_int,
>,
pub activate: ::std::option::Option<unsafe extern "C" fn() -> ::std::os::raw::c_int>,
pub deactivate: ::std::option::Option<unsafe extern "C" fn() -> ::std::os::raw::c_int>,
pub ub_write: ::std::option::Option<
unsafe extern "C" fn(str_: *const ::std::os::raw::c_char, str_length: usize) -> usize,
>,
pub flush:
::std::option::Option<unsafe extern "C" fn(server_context: *mut ::std::os::raw::c_void)>,
pub get_stat: ::std::option::Option<unsafe extern "C" fn() -> *mut zend_stat_t>,
pub getenv: ::std::option::Option<
unsafe extern "C" fn(
name: *const ::std::os::raw::c_char,
name_len: usize,
) -> *mut ::std::os::raw::c_char,
>,
pub sapi_error: ::std::option::Option<
unsafe extern "C" fn(
type_: ::std::os::raw::c_int,
error_msg: *const ::std::os::raw::c_char,
...
),
>,
pub header_handler: ::std::option::Option<
unsafe extern "C" fn(
sapi_header: *mut sapi_header_struct,
op: sapi_header_op_enum,
sapi_headers: *mut sapi_headers_struct,
) -> ::std::os::raw::c_int,
>,
pub send_headers: ::std::option::Option<
unsafe extern "C" fn(sapi_headers: *mut sapi_headers_struct) -> ::std::os::raw::c_int,
>,
pub send_header: ::std::option::Option<
unsafe extern "C" fn(
sapi_header: *mut sapi_header_struct,
server_context: *mut ::std::os::raw::c_void,
),
>,
pub read_post: ::std::option::Option<
unsafe extern "C" fn(buffer: *mut ::std::os::raw::c_char, count_bytes: usize) -> usize,
>,
pub read_cookies: ::std::option::Option<unsafe extern "C" fn() -> *mut ::std::os::raw::c_char>,
pub register_server_variables:
::std::option::Option<unsafe extern "C" fn(track_vars_array: *mut zval)>,
pub log_message: ::std::option::Option<
unsafe extern "C" fn(
message: *const ::std::os::raw::c_char,
syslog_type_int: ::std::os::raw::c_int,
),
>,
pub get_request_time:
::std::option::Option<unsafe extern "C" fn(request_time: *mut f64) -> zend_result>,
pub terminate_process: ::std::option::Option<unsafe extern "C" fn()>,
pub php_ini_path_override: *mut ::std::os::raw::c_char,
pub default_post_reader: ::std::option::Option<unsafe extern "C" fn()>,
pub treat_data: ::std::option::Option<
unsafe extern "C" fn(
arg: ::std::os::raw::c_int,
str_: *mut ::std::os::raw::c_char,
destArray: *mut zval,
),
>,
pub executable_location: *mut ::std::os::raw::c_char,
pub php_ini_ignore: ::std::os::raw::c_int,
pub php_ini_ignore_cwd: ::std::os::raw::c_int,
pub get_fd: ::std::option::Option<
unsafe extern "C" fn(fd: *mut ::std::os::raw::c_int) -> ::std::os::raw::c_int,
>,
pub force_http_10: ::std::option::Option<unsafe extern "C" fn() -> ::std::os::raw::c_int>,
pub get_target_uid:
::std::option::Option<unsafe extern "C" fn(arg1: *mut uid_t) -> ::std::os::raw::c_int>,
pub get_target_gid:
::std::option::Option<unsafe extern "C" fn(arg1: *mut gid_t) -> ::std::os::raw::c_int>,
pub input_filter: ::std::option::Option<
unsafe extern "C" fn(
arg: ::std::os::raw::c_int,
var: *const ::std::os::raw::c_char,
val: *mut *mut ::std::os::raw::c_char,
val_len: usize,
new_val_len: *mut usize,
) -> ::std::os::raw::c_uint,
>,
pub ini_defaults:
::std::option::Option<unsafe extern "C" fn(configuration_hash: *mut HashTable)>,
pub phpinfo_as_text: ::std::os::raw::c_int,
pub ini_entries: *const ::std::os::raw::c_char,
pub additional_functions: *const zend_function_entry,
pub input_filter_init: ::std::option::Option<unsafe extern "C" fn() -> ::std::os::raw::c_uint>,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct _sapi_post_entry {
Expand Down
1 change: 1 addition & 0 deletions src/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ extern "C" {
pub fn ext_php_rs_zend_object_release(obj: *mut zend_object);
pub fn ext_php_rs_executor_globals() -> *mut zend_executor_globals;
pub fn ext_php_rs_sapi_globals() -> *mut sapi_globals_struct;
pub fn ext_php_rs_sapi_module() -> *mut sapi_module_struct;
pub fn ext_php_rs_zend_try_catch(
func: unsafe extern "C" fn(*const c_void) -> *const c_void,
ctx: *const c_void,
Expand Down
4 changes: 4 additions & 0 deletions src/wrapper.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ sapi_globals_struct *ext_php_rs_sapi_globals() {
#endif
}

sapi_module_struct *ext_php_rs_sapi_module() {
return &sapi_module;
}

bool ext_php_rs_zend_try_catch(void* (*callback)(void *), void *ctx, void **result) {
zend_try {
*result = callback(ctx);
Expand Down
1 change: 1 addition & 0 deletions src/wrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,6 @@ void *ext_php_rs_zend_object_alloc(size_t obj_size, zend_class_entry *ce);
void ext_php_rs_zend_object_release(zend_object *obj);
zend_executor_globals *ext_php_rs_executor_globals();;
sapi_globals_struct *ext_php_rs_sapi_globals();
sapi_module_struct *ext_php_rs_sapi_module();
bool ext_php_rs_zend_try_catch(void* (*callback)(void *), void *ctx, void **result);
void ext_php_rs_zend_bailout();
47 changes: 45 additions & 2 deletions src/zend/globals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ use crate::boxed::ZBox;
#[cfg(php82)]
use crate::ffi::zend_atomic_bool_store;
use crate::ffi::{
_sapi_globals_struct, _zend_executor_globals, ext_php_rs_executor_globals,
ext_php_rs_sapi_globals, zend_ini_entry,
_sapi_globals_struct, _sapi_module_struct, _zend_executor_globals, ext_php_rs_executor_globals,
ext_php_rs_sapi_globals, ext_php_rs_sapi_module, zend_ini_entry,
};
use crate::types::{ZendHashTable, ZendObject};

Expand All @@ -20,6 +20,9 @@ pub type ExecutorGlobals = _zend_executor_globals;
/// Stores global SAPI variables used in the PHP executor.
pub type SapiGlobals = _sapi_globals_struct;

/// Stores the SAPI module used in the PHP executor.
pub type SapiModule = _sapi_module_struct;

impl ExecutorGlobals {
/// Returns a reference to the PHP executor globals.
///
Expand Down Expand Up @@ -167,6 +170,40 @@ impl SapiGlobals {
}
}

impl SapiModule {
/// Returns a reference to the PHP SAPI module.
///
/// The executor globals are guarded by a RwLock. There can be multiple
/// immutable references at one time but only ever one mutable reference.
/// Attempting to retrieve the globals while already holding the global
/// guard will lead to a deadlock. Dropping the globals guard will release
/// the lock.
pub fn get() -> GlobalReadGuard<Self> {
// SAFETY: PHP executor globals are statically declared therefore should never
// return an invalid pointer.
let globals = unsafe { ext_php_rs_sapi_module().as_ref() }
.expect("Static executor globals were invalid");
let guard = SAPI_MODULE_LOCK.read();
GlobalReadGuard { globals, guard }
}

/// Returns a mutable reference to the PHP executor globals.
///
/// The executor globals are guarded by a RwLock. There can be multiple
/// immutable references at one time but only ever one mutable reference.
/// Attempting to retrieve the globals while already holding the global
/// guard will lead to a deadlock. Dropping the globals guard will release
/// the lock.
pub fn get_mut() -> GlobalWriteGuard<Self> {
// SAFETY: PHP executor globals are statically declared therefore should never
// return an invalid pointer.
let globals = unsafe { ext_php_rs_sapi_module().as_mut() }
.expect("Static executor globals were invalid");
let guard = SAPI_MODULE_LOCK.write();
GlobalWriteGuard { globals, guard }
}
}

/// Executor globals rwlock.
///
/// PHP provides no indication if the executor globals are being accessed so
Expand All @@ -179,6 +216,12 @@ static GLOBALS_LOCK: RwLock<()> = const_rwlock(());
/// this is only effective on the Rust side.
static SAPI_LOCK: RwLock<()> = const_rwlock(());

/// SAPI globals rwlock.
///
/// PHP provides no indication if the executor globals are being accessed so
/// this is only effective on the Rust side.
static SAPI_MODULE_LOCK: RwLock<()> = const_rwlock(());

/// Wrapper guard that contains a reference to a given type `T`. Dropping a
/// guard releases the lock on the relevant rwlock.
pub struct GlobalReadGuard<T: 'static> {
Expand Down
1 change: 1 addition & 0 deletions src/zend/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub use function::Function;
pub use function::FunctionEntry;
pub use globals::ExecutorGlobals;
pub use globals::SapiGlobals;
pub use globals::SapiModule;
pub use handlers::ZendObjectHandlers;
pub use ini_entry_def::IniEntryDef;
pub use module::ModuleEntry;
Expand Down