@@ -6601,6 +6601,242 @@ ZEND_METHOD(ReflectionProperty, isFinal)
66016601 _property_check_flag (INTERNAL_FUNCTION_PARAM_PASSTHRU , ZEND_ACC_FINAL );
66026602}
66036603
6604+ static zend_result get_ce_from_scope_name (zend_class_entry * * scope , zend_string * scope_name , zend_execute_data * execute_data )
6605+ {
6606+ if (!scope_name ) {
6607+ * scope = NULL ;
6608+ return SUCCESS ;
6609+ }
6610+
6611+ * scope = zend_lookup_class (scope_name );
6612+ if (!* scope ) {
6613+ zend_throw_error (NULL , "Class \"%s\" not found" , ZSTR_VAL (scope_name ));
6614+ return FAILURE ;
6615+ }
6616+ return SUCCESS ;
6617+ }
6618+
6619+ static zend_always_inline uint32_t set_visibility_to_visibility (uint32_t set_visibility )
6620+ {
6621+ switch (set_visibility ) {
6622+ case ZEND_ACC_PUBLIC_SET :
6623+ return ZEND_ACC_PUBLIC ;
6624+ case ZEND_ACC_PROTECTED_SET :
6625+ return ZEND_ACC_PROTECTED ;
6626+ case ZEND_ACC_PRIVATE_SET :
6627+ return ZEND_ACC_PRIVATE ;
6628+ EMPTY_SWITCH_DEFAULT_CASE ();
6629+ }
6630+ }
6631+
6632+ static bool check_visibility (uint32_t visibility , zend_class_entry * ce , zend_class_entry * scope )
6633+ {
6634+ if (!(visibility & ZEND_ACC_PUBLIC ) && (scope != ce )) {
6635+ if (!scope ) {
6636+ return false;
6637+ }
6638+ if (visibility & ZEND_ACC_PRIVATE ) {
6639+ return false;
6640+ }
6641+ ZEND_ASSERT (visibility & ZEND_ACC_PROTECTED );
6642+ if (!instanceof_function (scope , ce ) && !instanceof_function (ce , scope )) {
6643+ return false;
6644+ }
6645+ }
6646+ return true;
6647+ }
6648+
6649+ ZEND_METHOD (ReflectionProperty , isReadable )
6650+ {
6651+ reflection_object * intern ;
6652+ property_reference * ref ;
6653+ zend_string * scope_name ;
6654+ zend_object * obj = NULL ;
6655+
6656+ ZEND_PARSE_PARAMETERS_START (1 , 2 )
6657+ Z_PARAM_STR_OR_NULL (scope_name )
6658+ Z_PARAM_OPTIONAL
6659+ Z_PARAM_OBJ_OR_NULL (obj )
6660+ ZEND_PARSE_PARAMETERS_END ();
6661+
6662+ GET_REFLECTION_OBJECT_PTR (ref );
6663+
6664+ zend_property_info * prop = ref -> prop ;
6665+ if (prop && obj ) {
6666+ if (prop -> flags & ZEND_ACC_STATIC ) {
6667+ _DO_THROW ("null is expected as object argument for static properties" );
6668+ RETURN_THROWS ();
6669+ }
6670+ if (!instanceof_function (obj -> ce , prop -> ce )) {
6671+ _DO_THROW ("Given object is not an instance of the class this property was declared in" );
6672+ RETURN_THROWS ();
6673+ }
6674+ prop = reflection_property_get_effective_prop (ref , intern -> ce , obj );
6675+ }
6676+
6677+ zend_class_entry * ce = obj ? obj -> ce : intern -> ce ;
6678+ if (!prop ) {
6679+ if (obj && obj -> properties && zend_hash_find_ptr (obj -> properties , ref -> unmangled_name )) {
6680+ RETURN_TRUE ;
6681+ }
6682+ handle_magic_get :
6683+ if (ce -> __get ) {
6684+ if (obj && ce -> __isset ) {
6685+ uint32_t * guard = zend_get_property_guard (obj , ref -> unmangled_name );
6686+ if (!((* guard ) & ZEND_GUARD_PROPERTY_ISSET )) {
6687+ GC_ADDREF (obj );
6688+ * guard |= ZEND_GUARD_PROPERTY_ISSET ;
6689+ zval member ;
6690+ ZVAL_STR (& member , ref -> unmangled_name );
6691+ zend_call_known_instance_method_with_1_params (ce -> __isset , obj , return_value , & member );
6692+ * guard &= ~ZEND_GUARD_PROPERTY_ISSET ;
6693+ OBJ_RELEASE (obj );
6694+ return ;
6695+ }
6696+ }
6697+ RETURN_TRUE ;
6698+ }
6699+ if (obj && zend_lazy_object_must_init (obj )) {
6700+ obj = zend_lazy_object_init (obj );
6701+ if (!obj ) {
6702+ RETURN_THROWS ();
6703+ }
6704+ if (obj -> properties && zend_hash_find_ptr (obj -> properties , ref -> unmangled_name )) {
6705+ RETURN_TRUE ;
6706+ }
6707+ }
6708+ RETURN_FALSE ;
6709+ }
6710+
6711+ zend_class_entry * scope ;
6712+ if (get_ce_from_scope_name (& scope , scope_name , execute_data ) == FAILURE ) {
6713+ RETURN_THROWS ();
6714+ }
6715+
6716+ if (!check_visibility (prop -> flags & ZEND_ACC_PPP_MASK , prop -> ce , scope )) {
6717+ if (!(prop -> flags & ZEND_ACC_STATIC )) {
6718+ goto handle_magic_get ;
6719+ }
6720+ RETURN_FALSE ;
6721+ }
6722+
6723+ if (prop -> flags & ZEND_ACC_VIRTUAL ) {
6724+ ZEND_ASSERT (prop -> hooks );
6725+ if (!prop -> hooks [ZEND_PROPERTY_HOOK_GET ]) {
6726+ RETURN_FALSE ;
6727+ }
6728+ } else if (obj && (!prop -> hooks || !prop -> hooks [ZEND_PROPERTY_HOOK_GET ])) {
6729+ retry_declared :;
6730+ zval * prop_val = OBJ_PROP (obj , prop -> offset );
6731+ if (Z_TYPE_P (prop_val ) == IS_UNDEF ) {
6732+ if (zend_lazy_object_must_init (obj ) && (Z_PROP_FLAG_P (prop_val ) & IS_PROP_LAZY )) {
6733+ obj = zend_lazy_object_init (obj );
6734+ if (!obj ) {
6735+ RETURN_THROWS ();
6736+ }
6737+ goto retry_declared ;
6738+ }
6739+ if (!(Z_PROP_FLAG_P (prop_val ) & IS_PROP_UNINIT )) {
6740+ goto handle_magic_get ;
6741+ }
6742+ RETURN_FALSE ;
6743+ }
6744+ } else if (prop -> flags & ZEND_ACC_STATIC ) {
6745+ if (ce -> default_static_members_count && !CE_STATIC_MEMBERS (ce )) {
6746+ zend_class_init_statics (ce );
6747+ }
6748+ zval * prop_val = CE_STATIC_MEMBERS (ce ) + prop -> offset ;
6749+ RETURN_BOOL (!Z_ISUNDEF_P (prop_val ));
6750+ }
6751+
6752+ RETURN_TRUE ;
6753+ }
6754+
6755+ ZEND_METHOD (ReflectionProperty , isWritable )
6756+ {
6757+ reflection_object * intern ;
6758+ property_reference * ref ;
6759+ zend_string * scope_name ;
6760+ zend_object * obj = NULL ;
6761+
6762+ ZEND_PARSE_PARAMETERS_START (1 , 2 )
6763+ Z_PARAM_STR_OR_NULL (scope_name )
6764+ Z_PARAM_OPTIONAL
6765+ Z_PARAM_OBJ_OR_NULL (obj )
6766+ ZEND_PARSE_PARAMETERS_END ();
6767+
6768+ GET_REFLECTION_OBJECT_PTR (ref );
6769+
6770+ zend_property_info * prop = ref -> prop ;
6771+ if (prop && obj ) {
6772+ if (prop -> flags & ZEND_ACC_STATIC ) {
6773+ _DO_THROW ("null is expected as object argument for static properties" );
6774+ RETURN_THROWS ();
6775+ }
6776+ if (!instanceof_function (obj -> ce , prop -> ce )) {
6777+ _DO_THROW ("Given object is not an instance of the class this property was declared in" );
6778+ RETURN_THROWS ();
6779+ }
6780+ prop = reflection_property_get_effective_prop (ref , intern -> ce , obj );
6781+ }
6782+
6783+ zend_class_entry * ce = obj ? obj -> ce : intern -> ce ;
6784+ if (!prop ) {
6785+ if (!(ce -> ce_flags & ZEND_ACC_NO_DYNAMIC_PROPERTIES )) {
6786+ RETURN_TRUE ;
6787+ }
6788+ /* This path is effectively unreachable, but theoretically possible for
6789+ * two internal classes where ZEND_ACC_NO_DYNAMIC_PROPERTIES is only
6790+ * added to the subclass, in which case a ReflectionProperty can be
6791+ * constructed on the parent class, and then tested on the subclass. */
6792+ handle_magic_set :
6793+ RETURN_BOOL (ce -> __set );
6794+ }
6795+
6796+ zend_class_entry * scope ;
6797+ if (get_ce_from_scope_name (& scope , scope_name , execute_data ) == FAILURE ) {
6798+ RETURN_THROWS ();
6799+ }
6800+
6801+ if (!check_visibility (prop -> flags & ZEND_ACC_PPP_MASK , prop -> ce , scope )) {
6802+ if (!(prop -> flags & ZEND_ACC_STATIC )) {
6803+ goto handle_magic_set ;
6804+ }
6805+ RETURN_FALSE ;
6806+ }
6807+ uint32_t set_visibility = prop -> flags & ZEND_ACC_PPP_SET_MASK ;
6808+ if (!set_visibility ) {
6809+ set_visibility = zend_visibility_to_set_visibility (prop -> flags & ZEND_ACC_PPP_MASK );
6810+ }
6811+ if (!check_visibility (set_visibility_to_visibility (set_visibility ), prop -> ce , scope )) {
6812+ RETURN_FALSE ;
6813+ }
6814+
6815+ if (prop -> flags & ZEND_ACC_VIRTUAL ) {
6816+ ZEND_ASSERT (prop -> hooks );
6817+ if (!prop -> hooks [ZEND_PROPERTY_HOOK_SET ]) {
6818+ RETURN_FALSE ;
6819+ }
6820+ } else if (obj && (prop -> flags & ZEND_ACC_READONLY )) {
6821+ retry :;
6822+ zval * prop_val = OBJ_PROP (obj , prop -> offset );
6823+ if (Z_TYPE_P (prop_val ) == IS_UNDEF
6824+ && zend_lazy_object_must_init (obj )
6825+ && (Z_PROP_FLAG_P (prop_val ) & IS_PROP_LAZY )) {
6826+ obj = zend_lazy_object_init (obj );
6827+ if (!obj ) {
6828+ RETURN_THROWS ();
6829+ }
6830+ goto retry ;
6831+ }
6832+ if (Z_TYPE_P (prop_val ) != IS_UNDEF && !(Z_PROP_FLAG_P (prop_val ) & IS_PROP_REINITABLE )) {
6833+ RETURN_FALSE ;
6834+ }
6835+ }
6836+
6837+ RETURN_TRUE ;
6838+ }
6839+
66046840/* {{{ Constructor. Throws an Exception in case the given extension does not exist */
66056841ZEND_METHOD (ReflectionExtension , __construct )
66066842{
0 commit comments