diff --git a/allowed_bindings.rs b/allowed_bindings.rs index 2046ab527..40556e9e3 100644 --- a/allowed_bindings.rs +++ b/allowed_bindings.rs @@ -143,6 +143,7 @@ bind! { IS_CONSTANT_AST_EX, IS_DOUBLE, IS_FALSE, + IS_INDIRECT, IS_INTERNED_STRING_EX, IS_LONG, IS_MIXED, diff --git a/docsrs_bindings.rs b/docsrs_bindings.rs index 2617c4e6c..34da760b5 100644 --- a/docsrs_bindings.rs +++ b/docsrs_bindings.rs @@ -99,6 +99,7 @@ pub const IS_CONSTANT_AST: u32 = 11; pub const IS_CALLABLE: u32 = 12; pub const IS_VOID: u32 = 14; pub const IS_MIXED: u32 = 16; +pub const IS_INDIRECT: u32 = 12; pub const IS_PTR: u32 = 13; pub const _IS_BOOL: u32 = 18; pub const Z_TYPE_FLAGS_SHIFT: u32 = 8; diff --git a/src/flags.rs b/src/flags.rs index 60897a065..9e814d2a2 100644 --- a/src/flags.rs +++ b/src/flags.rs @@ -8,14 +8,14 @@ use crate::ffi::{ CONST_CS, CONST_DEPRECATED, CONST_NO_FILE_CACHE, CONST_PERSISTENT, E_COMPILE_ERROR, E_COMPILE_WARNING, E_CORE_ERROR, E_CORE_WARNING, E_DEPRECATED, E_ERROR, E_NOTICE, E_PARSE, E_RECOVERABLE_ERROR, E_STRICT, E_USER_DEPRECATED, E_USER_ERROR, E_USER_NOTICE, E_USER_WARNING, - E_WARNING, IS_ARRAY, IS_CALLABLE, IS_CONSTANT_AST, IS_DOUBLE, IS_FALSE, IS_LONG, IS_MIXED, - IS_NULL, IS_OBJECT, IS_PTR, IS_REFERENCE, IS_RESOURCE, IS_STRING, IS_TRUE, IS_TYPE_COLLECTABLE, - IS_TYPE_REFCOUNTED, IS_UNDEF, IS_VOID, PHP_INI_ALL, PHP_INI_PERDIR, PHP_INI_SYSTEM, - PHP_INI_USER, ZEND_ACC_ABSTRACT, ZEND_ACC_ANON_CLASS, ZEND_ACC_CALL_VIA_TRAMPOLINE, - ZEND_ACC_CHANGED, ZEND_ACC_CLOSURE, ZEND_ACC_CONSTANTS_UPDATED, ZEND_ACC_CTOR, - ZEND_ACC_DEPRECATED, ZEND_ACC_DONE_PASS_TWO, ZEND_ACC_EARLY_BINDING, ZEND_ACC_FAKE_CLOSURE, - ZEND_ACC_FINAL, ZEND_ACC_GENERATOR, ZEND_ACC_HAS_FINALLY_BLOCK, ZEND_ACC_HAS_RETURN_TYPE, - ZEND_ACC_HAS_TYPE_HINTS, ZEND_ACC_HEAP_RT_CACHE, ZEND_ACC_IMMUTABLE, + E_WARNING, IS_ARRAY, IS_CALLABLE, IS_CONSTANT_AST, IS_DOUBLE, IS_FALSE, IS_INDIRECT, IS_LONG, + IS_MIXED, IS_NULL, IS_OBJECT, IS_PTR, IS_REFERENCE, IS_RESOURCE, IS_STRING, IS_TRUE, + IS_TYPE_COLLECTABLE, IS_TYPE_REFCOUNTED, IS_UNDEF, IS_VOID, PHP_INI_ALL, PHP_INI_PERDIR, + PHP_INI_SYSTEM, PHP_INI_USER, ZEND_ACC_ABSTRACT, ZEND_ACC_ANON_CLASS, + ZEND_ACC_CALL_VIA_TRAMPOLINE, ZEND_ACC_CHANGED, ZEND_ACC_CLOSURE, ZEND_ACC_CONSTANTS_UPDATED, + ZEND_ACC_CTOR, ZEND_ACC_DEPRECATED, ZEND_ACC_DONE_PASS_TWO, ZEND_ACC_EARLY_BINDING, + ZEND_ACC_FAKE_CLOSURE, ZEND_ACC_FINAL, ZEND_ACC_GENERATOR, ZEND_ACC_HAS_FINALLY_BLOCK, + ZEND_ACC_HAS_RETURN_TYPE, ZEND_ACC_HAS_TYPE_HINTS, ZEND_ACC_HEAP_RT_CACHE, ZEND_ACC_IMMUTABLE, ZEND_ACC_IMPLICIT_ABSTRACT_CLASS, ZEND_ACC_INTERFACE, ZEND_ACC_LINKED, ZEND_ACC_NEARLY_LINKED, ZEND_ACC_NEVER_CACHE, ZEND_ACC_NO_DYNAMIC_PROPERTIES, ZEND_ACC_PRELOADED, ZEND_ACC_PRIVATE, ZEND_ACC_PROMOTED, ZEND_ACC_PROTECTED, ZEND_ACC_PUBLIC, ZEND_ACC_RESOLVED_INTERFACES, @@ -246,6 +246,7 @@ pub enum DataType { Mixed, Bool, Ptr, + Indirect, } impl Default for DataType { @@ -269,6 +270,7 @@ impl DataType { DataType::Object(_) => IS_OBJECT, DataType::Resource => IS_RESOURCE, DataType::Reference => IS_RESOURCE, + DataType::Indirect => IS_INDIRECT, DataType::Callable => IS_CALLABLE, DataType::ConstantExpression => IS_CONSTANT_AST, DataType::Void => IS_VOID, @@ -337,6 +339,7 @@ impl From for DataType { contains!(IS_VOID, Void); contains!(IS_PTR, Ptr); + contains!(IS_INDIRECT, Indirect); contains!(IS_CALLABLE, Callable); contains!(IS_CONSTANT_AST, ConstantExpression); contains!(IS_REFERENCE, Reference); @@ -379,6 +382,7 @@ impl Display for DataType { DataType::Bool => write!(f, "Bool"), DataType::Mixed => write!(f, "Mixed"), DataType::Ptr => write!(f, "Pointer"), + DataType::Indirect => write!(f, "Indirect"), } } } @@ -388,9 +392,9 @@ mod tests { use super::DataType; use crate::ffi::{ IS_ARRAY, IS_ARRAY_EX, IS_CALLABLE, IS_CONSTANT_AST, IS_CONSTANT_AST_EX, IS_DOUBLE, - IS_FALSE, IS_INTERNED_STRING_EX, IS_LONG, IS_NULL, IS_OBJECT, IS_OBJECT_EX, IS_PTR, - IS_REFERENCE, IS_REFERENCE_EX, IS_RESOURCE, IS_RESOURCE_EX, IS_STRING, IS_STRING_EX, - IS_TRUE, IS_UNDEF, IS_VOID, + IS_FALSE, IS_INDIRECT, IS_INTERNED_STRING_EX, IS_LONG, IS_NULL, IS_OBJECT, IS_OBJECT_EX, + IS_PTR, IS_REFERENCE, IS_REFERENCE_EX, IS_RESOURCE, IS_RESOURCE_EX, IS_STRING, + IS_STRING_EX, IS_TRUE, IS_UNDEF, IS_VOID, }; use std::convert::TryFrom; @@ -414,7 +418,7 @@ mod tests { test!(IS_RESOURCE, Resource); test!(IS_REFERENCE, Reference); test!(IS_CONSTANT_AST, ConstantExpression); - test!(IS_CALLABLE, Callable); + test!(IS_INDIRECT, Indirect); test!(IS_VOID, Void); test!(IS_PTR, Ptr); diff --git a/src/types/zval.rs b/src/types/zval.rs index 94b62aa98..97def9a09 100644 --- a/src/types/zval.rs +++ b/src/types/zval.rs @@ -213,6 +213,24 @@ impl Zval { .try_call_method(name, params) } + /// Returns the value of the zval if it is an internal indirect reference. + pub fn indirect(&self) -> Option<&Zval> { + if self.is_indirect() { + Some(unsafe { &*(self.value.zv as *mut Zval) }) + } else { + None + } + } + + /// Returns a mutable reference to the zval if it is an internal indirect reference. + pub fn indirect_mut(&self) -> Option<&mut Zval> { + if self.is_indirect() { + Some(unsafe { &mut *(self.value.zv as *mut Zval) }) + } else { + None + } + } + /// Returns the value of the zval if it is a reference. pub fn reference(&self) -> Option<&Zval> { if self.is_reference() { @@ -329,6 +347,11 @@ impl Zval { self.get_type() == DataType::Reference } + /// Returns true if the zval is a reference, false otherwise. + pub fn is_indirect(&self) -> bool { + self.get_type() == DataType::Indirect + } + /// Returns true if the zval is callable, false otherwise. pub fn is_callable(&self) -> bool { let ptr: *const Self = self; @@ -601,6 +624,7 @@ impl Debug for Zval { DataType::ConstantExpression => field!(Option::<()>::None), DataType::Void => field!(Option::<()>::None), DataType::Bool => field!(self.bool()), + DataType::Indirect => field!(self.indirect()), // SAFETY: We are not accessing the pointer. DataType::Ptr => field!(unsafe { self.ptr::() }), };