From a616c4b4db95a0c635c07ea71c37e7eeec9278f5 Mon Sep 17 00:00:00 2001 From: Joe Hoyle Date: Wed, 19 Jul 2023 12:27:11 +0200 Subject: [PATCH 1/8] ZTS support for file globals --- src/ffi.rs | 1 + src/wrapper.c | 9 +++++++++ src/zend/globals.rs | 15 ++++++++------- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/ffi.rs b/src/ffi.rs index cd3a81c..465b509 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -28,6 +28,7 @@ extern "C" { pub fn ext_php_rs_executor_globals() -> *mut zend_executor_globals; pub fn ext_php_rs_process_globals() -> *mut php_core_globals; pub fn ext_php_rs_sapi_globals() -> *mut sapi_globals_struct; + pub fn ext_php_rs_file_globals() -> *mut php_file_globals; } include!(concat!(env!("OUT_DIR"), "/bindings.rs")); diff --git a/src/wrapper.c b/src/wrapper.c index 514882b..c88e2da 100644 --- a/src/wrapper.c +++ b/src/wrapper.c @@ -64,3 +64,12 @@ sapi_globals_struct *ext_php_rs_sapi_globals() { return &sapi_globals; #endif } + + +php_file_globals *ext_php_rs_file_globals() { +#ifdef ZTS + return TSRMG_FAST_BULK(file_globals_id, php_file_globals *); +#else + return &file_globals; +#endif +} diff --git a/src/zend/globals.rs b/src/zend/globals.rs index fee0d09..bf68e24 100644 --- a/src/zend/globals.rs +++ b/src/zend/globals.rs @@ -8,11 +8,11 @@ use parking_lot::{const_rwlock, RwLock, RwLockReadGuard, RwLockWriteGuard}; use crate::boxed::ZBox; use crate::ffi::{ - _zend_executor_globals, ext_php_rs_executor_globals, ext_php_rs_process_globals, - ext_php_rs_sapi_globals, file_globals, php_core_globals, php_file_globals, sapi_globals_struct, - sapi_header_struct, sapi_headers_struct, sapi_request_info, zend_is_auto_global, - TRACK_VARS_COOKIE, TRACK_VARS_ENV, TRACK_VARS_FILES, TRACK_VARS_GET, TRACK_VARS_POST, - TRACK_VARS_REQUEST, TRACK_VARS_SERVER, + _zend_executor_globals, ext_php_rs_executor_globals, ext_php_rs_file_globals, + ext_php_rs_process_globals, ext_php_rs_sapi_globals, php_core_globals, php_file_globals, + sapi_globals_struct, sapi_header_struct, sapi_headers_struct, sapi_request_info, + zend_is_auto_global, TRACK_VARS_COOKIE, TRACK_VARS_ENV, TRACK_VARS_FILES, TRACK_VARS_GET, + TRACK_VARS_POST, TRACK_VARS_REQUEST, TRACK_VARS_SERVER, }; use crate::types::{ZendHashTable, ZendObject, ZendStr}; @@ -378,7 +378,8 @@ impl FileGlobals { pub fn get() -> GlobalReadGuard { // SAFETY: PHP executor globals are statically declared therefore should never // return an invalid pointer. - let globals = unsafe { &file_globals }; + let globals = unsafe { ext_php_rs_file_globals().as_ref() } + .expect("Static file globals were invalid"); let guard = FILE_GLOBALS_LOCK.read(); GlobalReadGuard { globals, guard } } @@ -393,7 +394,7 @@ impl FileGlobals { pub fn get_mut() -> GlobalWriteGuard { // SAFETY: PHP executor globals are statically declared therefore should never // return an invalid pointer. - let globals = unsafe { &mut file_globals }; + let globals = unsafe { &mut *ext_php_rs_file_globals() }; let guard = SAPI_GLOBALS_LOCK.write(); GlobalWriteGuard { globals, guard } } From 0a2ecbcc39496f95e1e86bd7bd9073f02dd8d502 Mon Sep 17 00:00:00 2001 From: Joe Hoyle Date: Wed, 19 Jul 2023 13:00:24 +0200 Subject: [PATCH 2/8] Add helper function --- src/wrapper.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/wrapper.h b/src/wrapper.h index 62e6fa9..85d8d21 100644 --- a/src/wrapper.h +++ b/src/wrapper.h @@ -24,6 +24,7 @@ #include "zend_interfaces.h" #include "SAPI.h" #include "php_variables.h" +#include "file.h" zend_string *ext_php_rs_zend_string_init(const char *str, size_t len, bool persistent); void ext_php_rs_zend_string_release(zend_string *zs); @@ -36,3 +37,4 @@ void ext_php_rs_zend_object_release(zend_object *obj); zend_executor_globals *ext_php_rs_executor_globals(); php_core_globals *ext_php_rs_process_globals(); sapi_globals_struct *ext_php_rs_sapi_globals(); +php_file_globals *ext_php_rs_file_globals(); From ef52ef60e3b81ec0ca11a8272fe5b33cdc6fb349 Mon Sep 17 00:00:00 2001 From: Joe Hoyle Date: Wed, 19 Jul 2023 13:04:55 +0200 Subject: [PATCH 3/8] Remove file.h --- src/wrapper.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/wrapper.h b/src/wrapper.h index 85d8d21..f2747b7 100644 --- a/src/wrapper.h +++ b/src/wrapper.h @@ -24,7 +24,6 @@ #include "zend_interfaces.h" #include "SAPI.h" #include "php_variables.h" -#include "file.h" zend_string *ext_php_rs_zend_string_init(const char *str, size_t len, bool persistent); void ext_php_rs_zend_string_release(zend_string *zs); From 7b35476d04bdf628d20592751c2e12b7cd5c0588 Mon Sep 17 00:00:00 2001 From: Joe Hoyle Date: Wed, 19 Jul 2023 13:06:10 +0200 Subject: [PATCH 4/8] Implement IntoZvalDyn for Zval (#256) --- src/builders/module.rs | 3 ++- src/convert.rs | 10 ++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/builders/module.rs b/src/builders/module.rs index 01bc9e4..ee2b219 100644 --- a/src/builders/module.rs +++ b/src/builders/module.rs @@ -131,7 +131,8 @@ impl ModuleBuilder { /// This function can be useful if you need to do any final cleanup at the /// very end of a request, after all other resources have been released. For /// example, if your extension creates any persistent resources that last - /// beyond a single request, you could use this function to clean those up. # Arguments + /// beyond a single request, you could use this function to clean those up. + /// # Arguments /// /// * `func` - The function to be called when shutdown is requested. pub fn post_deactivate_function(mut self, func: extern "C" fn() -> i32) -> Self { diff --git a/src/convert.rs b/src/convert.rs index 8782370..e1e2169 100644 --- a/src/convert.rs +++ b/src/convert.rs @@ -218,3 +218,13 @@ impl IntoZvalDyn for T { Self::TYPE } } + +impl IntoZvalDyn for Zval { + fn as_zval(&self, _persistent: bool) -> Result { + Ok(self.shallow_clone()) + } + + fn get_type(&self) -> DataType { + self.get_type() + } +} From 3e378f8cdffbab3ff1d16eefd2d090e6ee6b7b1d Mon Sep 17 00:00:00 2001 From: Joe Hoyle Date: Wed, 19 Jul 2023 13:12:35 +0200 Subject: [PATCH 5/8] Add function for requesting VM interrupt (#257) --- allowed_bindings.rs | 4 +++- docsrs_bindings.rs | 7 +++++++ src/zend/globals.rs | 18 +++++++++++++++++- 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/allowed_bindings.rs b/allowed_bindings.rs index b1e2748..0cd8270 100644 --- a/allowed_bindings.rs +++ b/allowed_bindings.rs @@ -243,5 +243,7 @@ bind! { php_printf, __zend_malloc, tsrm_get_ls_cache, - executor_globals_offset + executor_globals_offset, + zend_atomic_bool_store, + zend_interrupt_function } diff --git a/docsrs_bindings.rs b/docsrs_bindings.rs index 1888949..a7cc5a1 100644 --- a/docsrs_bindings.rs +++ b/docsrs_bindings.rs @@ -670,6 +670,10 @@ pub struct _zend_class_entry__bindgen_ty_4__bindgen_ty_2 { pub builtin_functions: *const _zend_function_entry, pub module: *mut _zend_module_entry, } +extern "C" { + pub static mut zend_interrupt_function: + ::std::option::Option; +} extern "C" { pub static mut zend_standard_class_def: *mut zend_class_entry; } @@ -1053,6 +1057,9 @@ pub struct zend_atomic_bool_s { pub value: u8, } pub type zend_atomic_bool = zend_atomic_bool_s; +extern "C" { + pub fn zend_atomic_bool_store(obj: *mut zend_atomic_bool, desired: bool); +} #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct _zend_stack { diff --git a/src/zend/globals.rs b/src/zend/globals.rs index 0f2cae8..c9a7a0d 100644 --- a/src/zend/globals.rs +++ b/src/zend/globals.rs @@ -5,8 +5,9 @@ use std::ops::{Deref, DerefMut}; use parking_lot::{const_rwlock, RwLock, RwLockReadGuard, RwLockWriteGuard}; use crate::boxed::ZBox; +#[cfg(php82)] +use crate::ffi::zend_atomic_bool_store; use crate::ffi::{_zend_executor_globals, ext_php_rs_executor_globals}; - use crate::types::{ZendHashTable, ZendObject}; /// Stores global variables used in the PHP executor. @@ -70,6 +71,21 @@ impl ExecutorGlobals { // SAFETY: `as_mut` checks for null. Some(unsafe { ZBox::from_raw(exception_ptr.as_mut()?) }) } + + /// Request an interrupt of the PHP VM. This will call the registered + /// interrupt handler function. + /// set with [`crate::ffi::zend_interrupt_function`]. + pub fn request_interrupt(&mut self) { + cfg_if::cfg_if! { + if #[cfg(php82)] { + unsafe { + zend_atomic_bool_store(&mut self.vm_interrupt, true); + } + } else { + self.vm_interrupt = true; + } + } + } } /// Executor globals rwlock. From 4e8bec79953a7d01456ef88ae72a161b62d7678d Mon Sep 17 00:00:00 2001 From: Joe Hoyle Date: Wed, 19 Jul 2023 13:13:12 +0200 Subject: [PATCH 6/8] Add helper for class name (#255) --- src/zend/class.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/zend/class.rs b/src/zend/class.rs index dc06a32..6e7f796 100644 --- a/src/zend/class.rs +++ b/src/zend/class.rs @@ -79,6 +79,10 @@ impl ClassEntry { Self::try_find(name.as_str().ok()?) } } + + pub fn name(&self) -> Option<&str> { + unsafe { self.name.as_ref().and_then(|s| s.as_str().ok()) } + } } impl PartialEq for ClassEntry { From 42ef04a8aed8eb72665c4b43c19a0dfcdb75283d Mon Sep 17 00:00:00 2001 From: Joe Hoyle Date: Wed, 19 Jul 2023 13:15:36 +0200 Subject: [PATCH 7/8] Add function type_() method (#254) --- allowed_bindings.rs | 3 +++ docsrs_bindings.rs | 3 +++ src/flags.rs | 23 +++++++++++++++++++++-- 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/allowed_bindings.rs b/allowed_bindings.rs index 0cd8270..7252bea 100644 --- a/allowed_bindings.rs +++ b/allowed_bindings.rs @@ -217,6 +217,9 @@ bind! { _ZEND_TYPE_NULLABLE_BIT, ts_rsrc_id, _ZEND_TYPE_NAME_BIT, + ZEND_INTERNAL_FUNCTION, + ZEND_USER_FUNCTION, + ZEND_EVAL_CODE, zval_ptr_dtor, zend_refcounted_h, zend_is_true, diff --git a/docsrs_bindings.rs b/docsrs_bindings.rs index a7cc5a1..1ba4175 100644 --- a/docsrs_bindings.rs +++ b/docsrs_bindings.rs @@ -91,6 +91,9 @@ pub const ZEND_ACC_GENERATOR: u32 = 16777216; pub const ZEND_ACC_DONE_PASS_TWO: u32 = 33554432; pub const ZEND_ACC_HEAP_RT_CACHE: u32 = 67108864; pub const ZEND_ACC_STRICT_TYPES: u32 = 2147483648; +pub const ZEND_INTERNAL_FUNCTION: u32 = 1; +pub const ZEND_USER_FUNCTION: u32 = 2; +pub const ZEND_EVAL_CODE: u32 = 4; pub const ZEND_ISEMPTY: u32 = 1; pub const _ZEND_SEND_MODE_SHIFT: u32 = 25; pub const _ZEND_IS_VARIADIC_BIT: u32 = 134217728; diff --git a/src/flags.rs b/src/flags.rs index 2dcdb6a..d2fbc37 100644 --- a/src/flags.rs +++ b/src/flags.rs @@ -20,8 +20,9 @@ use crate::ffi::{ ZEND_ACC_PROMOTED, ZEND_ACC_PROTECTED, ZEND_ACC_PUBLIC, ZEND_ACC_RESOLVED_INTERFACES, ZEND_ACC_RESOLVED_PARENT, ZEND_ACC_RETURN_REFERENCE, ZEND_ACC_STATIC, ZEND_ACC_STRICT_TYPES, ZEND_ACC_TOP_LEVEL, ZEND_ACC_TRAIT, ZEND_ACC_TRAIT_CLONE, ZEND_ACC_UNRESOLVED_VARIANCE, - ZEND_ACC_USES_THIS, ZEND_ACC_USE_GUARDS, ZEND_ACC_VARIADIC, ZEND_HAS_STATIC_IN_METHODS, - Z_TYPE_FLAGS_SHIFT, _IS_BOOL, + ZEND_ACC_USES_THIS, ZEND_ACC_USE_GUARDS, ZEND_ACC_VARIADIC, ZEND_EVAL_CODE, + ZEND_HAS_STATIC_IN_METHODS, ZEND_INTERNAL_FUNCTION, ZEND_USER_FUNCTION, Z_TYPE_FLAGS_SHIFT, + _IS_BOOL, }; use std::{convert::TryFrom, fmt::Display}; @@ -193,6 +194,24 @@ bitflags! { const UserDeprecated = E_USER_DEPRECATED; } } +#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy)] +pub enum FunctionType { + Internal, + User, + Eval, +} + +impl From for FunctionType { + #[allow(clippy::bad_bit_mask)] + fn from(value: u8) -> Self { + match value as _ { + ZEND_INTERNAL_FUNCTION => Self::Internal, + ZEND_USER_FUNCTION => Self::User, + ZEND_EVAL_CODE => Self::Eval, + _ => panic!("Unknown function type: {}", value), + } + } +} /// Valid data types for PHP. #[repr(C, u8)] From e30f1272da7c9e5e4913063fcbc67db0c03a2606 Mon Sep 17 00:00:00 2001 From: Joe Hoyle Date: Wed, 19 Jul 2023 13:27:10 +0200 Subject: [PATCH 8/8] Add file_globals_id to allowed bindings --- allowed_bindings.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/allowed_bindings.rs b/allowed_bindings.rs index 8578480..d9996ec 100644 --- a/allowed_bindings.rs +++ b/allowed_bindings.rs @@ -252,6 +252,7 @@ bind! { sapi_globals_offset, php_file_globals, file_globals, + file_globals_id, TRACK_VARS_POST, TRACK_VARS_GET, TRACK_VARS_COOKIE,