@@ -6601,6 +6601,215 @@ 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+ RETURN_FALSE ;
6700+ }
6701+
6702+ zend_class_entry * scope ;
6703+ if (get_ce_from_scope_name (& scope , scope_name , execute_data ) == FAILURE ) {
6704+ RETURN_THROWS ();
6705+ }
6706+
6707+ if (!check_visibility (prop -> flags & ZEND_ACC_PPP_MASK , prop -> ce , scope )) {
6708+ if (!(prop -> flags & ZEND_ACC_STATIC )) {
6709+ goto handle_magic_get ;
6710+ }
6711+ RETURN_FALSE ;
6712+ }
6713+
6714+ if (prop -> flags & ZEND_ACC_VIRTUAL ) {
6715+ ZEND_ASSERT (prop -> hooks );
6716+ if (!prop -> hooks [ZEND_PROPERTY_HOOK_GET ]) {
6717+ RETURN_FALSE ;
6718+ }
6719+ } else if (obj && (!prop -> hooks || !prop -> hooks [ZEND_PROPERTY_HOOK_GET ])) {
6720+ zval * prop_val = OBJ_PROP (obj , prop -> offset );
6721+ if (Z_TYPE_P (prop_val ) == IS_UNDEF ) {
6722+ if (!(Z_PROP_FLAG_P (prop_val ) & IS_PROP_UNINIT )) {
6723+ goto handle_magic_get ;
6724+ }
6725+ RETURN_FALSE ;
6726+ }
6727+ } else if (prop -> flags & ZEND_ACC_STATIC ) {
6728+ if (ce -> default_static_members_count && !CE_STATIC_MEMBERS (ce )) {
6729+ zend_class_init_statics (ce );
6730+ }
6731+ zval * prop_val = CE_STATIC_MEMBERS (ce ) + prop -> offset ;
6732+ RETURN_BOOL (!Z_ISUNDEF_P (prop_val ));
6733+ }
6734+
6735+ RETURN_TRUE ;
6736+ }
6737+
6738+ ZEND_METHOD (ReflectionProperty , isWritable )
6739+ {
6740+ reflection_object * intern ;
6741+ property_reference * ref ;
6742+ zend_string * scope_name ;
6743+ zend_object * obj = NULL ;
6744+
6745+ ZEND_PARSE_PARAMETERS_START (1 , 2 )
6746+ Z_PARAM_STR_OR_NULL (scope_name )
6747+ Z_PARAM_OPTIONAL
6748+ Z_PARAM_OBJ_OR_NULL (obj )
6749+ ZEND_PARSE_PARAMETERS_END ();
6750+
6751+ GET_REFLECTION_OBJECT_PTR (ref );
6752+
6753+ zend_property_info * prop = ref -> prop ;
6754+ if (prop && obj ) {
6755+ if (prop -> flags & ZEND_ACC_STATIC ) {
6756+ _DO_THROW ("null is expected as object argument for static properties" );
6757+ RETURN_THROWS ();
6758+ }
6759+ if (!instanceof_function (obj -> ce , prop -> ce )) {
6760+ _DO_THROW ("Given object is not an instance of the class this property was declared in" );
6761+ RETURN_THROWS ();
6762+ }
6763+ prop = reflection_property_get_effective_prop (ref , intern -> ce , obj );
6764+ }
6765+
6766+ zend_class_entry * ce = obj ? obj -> ce : intern -> ce ;
6767+ if (!prop ) {
6768+ if (!(ce -> ce_flags & ZEND_ACC_NO_DYNAMIC_PROPERTIES )) {
6769+ RETURN_TRUE ;
6770+ }
6771+ /* This path is effectively unreachable, but theoretically possible for
6772+ * two internal classes where ZEND_ACC_NO_DYNAMIC_PROPERTIES is only
6773+ * added to the subclass, in which case a ReflectionProperty can be
6774+ * constructed on the parent class, and then tested on the subclass. */
6775+ handle_magic_set :
6776+ RETURN_BOOL (ce -> __set );
6777+ }
6778+
6779+ zend_class_entry * scope ;
6780+ if (get_ce_from_scope_name (& scope , scope_name , execute_data ) == FAILURE ) {
6781+ RETURN_THROWS ();
6782+ }
6783+
6784+ if (!check_visibility (prop -> flags & ZEND_ACC_PPP_MASK , prop -> ce , scope )) {
6785+ if (!(prop -> flags & ZEND_ACC_STATIC )) {
6786+ goto handle_magic_set ;
6787+ }
6788+ RETURN_FALSE ;
6789+ }
6790+ uint32_t set_visibility = prop -> flags & ZEND_ACC_PPP_SET_MASK ;
6791+ if (!set_visibility ) {
6792+ set_visibility = zend_visibility_to_set_visibility (prop -> flags & ZEND_ACC_PPP_MASK );
6793+ }
6794+ if (!check_visibility (set_visibility_to_visibility (set_visibility ), prop -> ce , scope )) {
6795+ RETURN_FALSE ;
6796+ }
6797+
6798+ if (prop -> flags & ZEND_ACC_VIRTUAL ) {
6799+ ZEND_ASSERT (prop -> hooks );
6800+ if (!prop -> hooks [ZEND_PROPERTY_HOOK_SET ]) {
6801+ RETURN_FALSE ;
6802+ }
6803+ } else if (obj && (prop -> flags & ZEND_ACC_READONLY )) {
6804+ zval * prop_val = OBJ_PROP (obj , prop -> offset );
6805+ if (Z_TYPE_P (prop_val ) != IS_UNDEF && !(Z_PROP_FLAG_P (prop_val ) & IS_PROP_REINITABLE )) {
6806+ RETURN_FALSE ;
6807+ }
6808+ }
6809+
6810+ RETURN_TRUE ;
6811+ }
6812+
66046813/* {{{ Constructor. Throws an Exception in case the given extension does not exist */
66056814ZEND_METHOD (ReflectionExtension , __construct )
66066815{
0 commit comments