@ -325,22 +325,19 @@ static zend_always_inline int zend_verify_property_access(zend_property_info *pr
if ( property_info - > flags & ZEND_ACC_PUBLIC ) {
return 1 ;
} else if ( property_info - > flags & ZEND_ACC_PRIVATE ) {
} else {
if ( EG ( fake_scope ) ) {
scope = EG ( fake_scope ) ;
} else {
scope = zend_get_executed_scope ( ) ;
}
return ( ce = = scope | | property_info - > ce = = scope ) ;
} else if ( property_info - > flags & ZEND_ACC_PROTECTED ) {
if ( EG ( fake_scope ) ) {
scope = EG ( fake_scope ) ;
if ( property_info - > flags & ZEND_ACC_PRIVATE ) {
return property_info - > ce = = scope ;
} else {
scope = zend_get_executed_scope ( ) ;
ZEND_ASSERT ( property_info - > flags & ZEND_ACC_PROTECTED ) ;
return zend_check_protected ( property_info - > ce , scope ) ;
}
return zend_check_protected ( property_info - > ce , scope ) ;
}
return 0 ;
}
/* }}} */
@ -377,39 +374,62 @@ static zend_always_inline uintptr_t zend_get_property_offset(zend_class_entry *c
if ( EXPECTED ( zv ! = NULL ) ) {
property_info = ( zend_property_info * ) Z_PTR_P ( zv ) ;
flags = property_info - > flags ;
if ( UNEXPECTED ( ( flags & ZEND_ACC_SHADOW ) ! = 0 ) ) {
/* if it's a shadow - go to access it's private */
property_info = NULL ;
} else {
if ( EXPECTED ( zend_verify_property_access ( property_info , ce ) ! = 0 ) ) {
if ( UNEXPECTED ( ! ( flags & ZEND_ACC_CHANGED ) )
| | UNEXPECTED ( ( flags & ZEND_ACC_PRIVATE ) ) ) {
if ( UNEXPECTED ( ( flags & ZEND_ACC_STATIC ) ! = 0 ) ) {
if ( ! silent ) {
zend_error ( E_NOTICE , " Accessing static property %s::$%s as non static " , ZSTR_VAL ( ce - > name ) , ZSTR_VAL ( member ) ) ;
}
return ZEND_DYNAMIC_PROPERTY_OFFSET ;
if ( flags & ZEND_ACC_PUBLIC ) {
if ( ! ( flags & ZEND_ACC_CHANGED ) ) {
no_changed :
if ( UNEXPECTED ( ( flags & ZEND_ACC_STATIC ) ! = 0 ) ) {
if ( ! silent ) {
zend_error ( E_NOTICE , " Accessing static property %s::$%s as non static " , ZSTR_VAL ( ce - > name ) , ZSTR_VAL ( member ) ) ;
}
goto exit ;
return ZEND_DYNAMIC_PROPERTY_OFFSET ;
}
goto exit ;
}
goto check_scope ;
} else {
if ( EG ( fake_scope ) ) {
scope = EG ( fake_scope ) ;
} else {
scope = zend_get_executed_scope ( ) ;
}
if ( flags & ZEND_ACC_PRIVATE ) {
if ( property_info - > ce = = scope ) {
goto no_changed ;
} else if ( property_info - > ce ! = ce ) {
/* if it's a shadow - go to access it's private */
property_info = NULL ;
} else {
/* Try to look in the scope instead */
property_info = ZEND_WRONG_PROPERTY_INFO ;
}
} else {
/* Try to look in the scope instead */
property_info = ZEND_WRONG_PROPERTY_INFO ;
ZEND_ASSERT ( flags & ZEND_ACC_PROTECTED ) ;
if ( zend_check_protected ( property_info - > ce , scope ) ) {
if ( ! ( flags & ZEND_ACC_CHANGED ) ) {
goto no_changed ;
}
} else {
/* Try to look in the scope instead */
property_info = ZEND_WRONG_PROPERTY_INFO ;
}
}
}
}
if ( EG ( fake_scope ) ) {
scope = EG ( fake_scope ) ;
} else {
scope = zend_get_executed_scope ( ) ;
check_scope :
if ( EG ( fake_scope ) ) {
scope = EG ( fake_scope ) ;
} else {
scope = zend_get_executed_scope ( ) ;
}
}
if ( scope ! = ce
& & scope
& & is_derived_class ( ce , scope )
& & ( zv = zend_hash_find ( & scope - > properties_info , member ) ) ! = NULL
& & ( ( zend_property_info * ) Z_PTR_P ( zv ) ) - > flags & ZEND_ACC_PRIVATE ) {
& & ( ( zend_property_info * ) Z_PTR_P ( zv ) ) - > flags & ZEND_ACC_PRIVATE
& & ( ( zend_property_info * ) Z_PTR_P ( zv ) ) - > ce = = scope ) {
property_info = ( zend_property_info * ) Z_PTR_P ( zv ) ;
if ( UNEXPECTED ( ( property_info - > flags & ZEND_ACC_STATIC ) ! = 0 ) ) {
return ZEND_DYNAMIC_PROPERTY_OFFSET ;
@ -457,38 +477,61 @@ ZEND_API zend_property_info *zend_get_property_info(zend_class_entry *ce, zend_s
if ( EXPECTED ( zv ! = NULL ) ) {
property_info = ( zend_property_info * ) Z_PTR_P ( zv ) ;
flags = property_info - > flags ;
if ( UNEXPECTED ( ( flags & ZEND_ACC_SHADOW ) ! = 0 ) ) {
/* if it's a shadow - go to access it's private */
property_info = NULL ;
} else {
if ( EXPECTED ( zend_verify_property_access ( property_info , ce ) ! = 0 ) ) {
if ( UNEXPECTED ( ! ( flags & ZEND_ACC_CHANGED ) )
| | UNEXPECTED ( ( flags & ZEND_ACC_PRIVATE ) ) ) {
if ( UNEXPECTED ( ( flags & ZEND_ACC_STATIC ) ! = 0 ) ) {
if ( ! silent ) {
zend_error ( E_NOTICE , " Accessing static property %s::$%s as non static " , ZSTR_VAL ( ce - > name ) , ZSTR_VAL ( member ) ) ;
}
if ( flags & ZEND_ACC_PUBLIC ) {
if ( ! ( flags & ZEND_ACC_CHANGED ) ) {
no_changed :
if ( UNEXPECTED ( ( flags & ZEND_ACC_STATIC ) ! = 0 ) ) {
if ( ! silent ) {
zend_error ( E_NOTICE , " Accessing static property %s::$%s as non static " , ZSTR_VAL ( ce - > name ) , ZSTR_VAL ( member ) ) ;
}
goto exit ;
}
goto exit ;
}
goto check_scope ;
} else {
if ( EG ( fake_scope ) ) {
scope = EG ( fake_scope ) ;
} else {
scope = zend_get_executed_scope ( ) ;
}
if ( flags & ZEND_ACC_PRIVATE ) {
if ( property_info - > ce = = scope ) {
goto no_changed ;
} else if ( property_info - > ce ! = ce ) {
/* if it's a shadow - go to access it's private */
property_info = NULL ;
} else {
/* Try to look in the scope instead */
property_info = ZEND_WRONG_PROPERTY_INFO ;
}
} else {
/* Try to look in the scope instead */
property_info = ZEND_WRONG_PROPERTY_INFO ;
ZEND_ASSERT ( flags & ZEND_ACC_PROTECTED ) ;
if ( zend_check_protected ( property_info - > ce , scope ) ) {
if ( ! ( flags & ZEND_ACC_CHANGED ) ) {
goto no_changed ;
}
} else {
/* Try to look in the scope instead */
property_info = ZEND_WRONG_PROPERTY_INFO ;
}
}
}
}
if ( EG ( fake_scope ) ) {
scope = EG ( fake_scope ) ;
} else {
scope = zend_get_executed_scope ( ) ;
check_scope :
if ( EG ( fake_scope ) ) {
scope = EG ( fake_scope ) ;
} else {
scope = zend_get_executed_scope ( ) ;
}
}
if ( scope ! = ce
& & scope
& & is_derived_class ( ce , scope )
& & ( zv = zend_hash_find ( & scope - > properties_info , member ) ) ! = NULL
& & ( ( zend_property_info * ) Z_PTR_P ( zv ) ) - > flags & ZEND_ACC_PRIVATE ) {
& & ( ( zend_property_info * ) Z_PTR_P ( zv ) ) - > flags & ZEND_ACC_PRIVATE
& & ( ( zend_property_info * ) Z_PTR_P ( zv ) ) - > ce = = scope ) {
property_info = ( zend_property_info * ) Z_PTR_P ( zv ) ;
} else if ( UNEXPECTED ( property_info = = NULL ) ) {
exit_dynamic :
@ -519,35 +562,43 @@ ZEND_API int zend_check_property_access(zend_object *zobj, zend_string *prop_inf
const char * prop_name ;
zend_string * member ;
size_t prop_name_len ;
zend_class_entry * scope ;
if ( ZSTR_VAL ( prop_info_name ) [ 0 ] = = 0 ) {
zend_unmangle_property_name_ex ( prop_info_name , & class_name , & prop_name , & prop_name_len ) ;
member = zend_string_init ( prop_name , prop_name_len , 0 ) ;
} else {
member = zend_string_copy ( prop_info_name ) ;
}
property_info = zend_get_property_info ( zobj - > ce , member , 1 ) ;
zend_string_release_ex ( member , 0 ) ;
if ( property_info = = NULL ) {
/* undefined public property */
if ( class_name & & class_name [ 0 ] ! = ' * ' ) {
/* we we're looking for a private prop */
property_info = zend_get_property_info ( zobj - > ce , member , 1 ) ;
zend_string_release_ex ( member , 0 ) ;
if ( property_info = = NULL ) {
if ( class_name [ 0 ] ! = ' * ' ) {
/* we we're looking for a private prop */
return FAILURE ;
}
return SUCCESS ;
} else if ( property_info = = ZEND_WRONG_PROPERTY_INFO ) {
return FAILURE ;
}
return SUCCESS ;
} else if ( property_info = = ZEND_WRONG_PROPERTY_INFO ) {
return FAILURE ;
}
if ( class_name & & class_name [ 0 ] ! = ' * ' ) {
if ( ! ( property_info - > flags & ZEND_ACC_PRIVATE ) ) {
/* we we're looking for a private prop but found a non private one of the same name */
return FAILURE ;
} else if ( strcmp ( ZSTR_VAL ( prop_info_name ) + 1 , ZSTR_VAL ( property_info - > name ) + 1 ) ) {
/* we we're looking for a private prop but found a private one of the same name but another class */
if ( class_name [ 0 ] ! = ' * ' ) {
if ( ! ( property_info - > flags & ZEND_ACC_PRIVATE ) ) {
/* we we're looking for a private prop but found a non private one of the same name */
return FAILURE ;
} else if ( strcmp ( ZSTR_VAL ( prop_info_name ) + 1 , ZSTR_VAL ( property_info - > name ) + 1 ) ) {
/* we we're looking for a private prop but found a private one of the same name but another class */
return FAILURE ;
}
} else {
ZEND_ASSERT ( property_info - > flags & ZEND_ACC_PROTECTED ) ;
}
} else {
property_info = zend_get_property_info ( zobj - > ce , prop_info_name , 1 ) ;
if ( property_info = = NULL ) {
return SUCCESS ;
} else if ( property_info = = ZEND_WRONG_PROPERTY_INFO ) {
return FAILURE ;
}
ZEND_ASSERT ( property_info - > flags & ZEND_ACC_PUBLIC ) ;
}
return zend_verify_property_access ( property_info , zobj - > ce ) ? SUCCESS : FAILURE ;
return SUCCESS ;
}
/* }}} */
@ -1457,40 +1508,38 @@ ZEND_API zend_function *zend_std_get_constructor(zend_object *zobj) /* {{{ */
if ( constructor ) {
if ( constructor - > op_array . fn_flags & ZEND_ACC_PUBLIC ) {
/* No further checks necessary */
} else if ( constructor - > op_array . fn_flags & ZEND_ACC_PRIVATE ) {
/* Ensure that if we're calling a private function, we're allowed to do so.
*/
} else {
if ( EG ( fake_scope ) ) {
scope = EG ( fake_scope ) ;
} else {
scope = zend_get_executed_scope ( ) ;
}
if ( UNEXPECTED ( constructor - > common . scope ! = scope ) ) {
if ( scope ) {
zend_throw_error ( NULL , " Call to private %s::%s() from context '%s' " , ZSTR_VAL ( constructor - > common . scope - > name ) , ZSTR_VAL ( constructor - > common . function_name ) , ZSTR_VAL ( scope - > name ) ) ;
constructor = NULL ;
} else {
zend_throw_error ( NULL , " Call to private %s::%s() from invalid context " , ZSTR_VAL ( constructor - > common . scope - > name ) , ZSTR_VAL ( constructor - > common . function_name ) ) ;
constructor = NULL ;
if ( constructor - > op_array . fn_flags & ZEND_ACC_PRIVATE ) {
/* Ensure that if we're calling a private function, we're allowed to do so.
*/
if ( UNEXPECTED ( constructor - > common . scope ! = scope ) ) {
if ( scope ) {
zend_throw_error ( NULL , " Call to private %s::%s() from context '%s' " , ZSTR_VAL ( constructor - > common . scope - > name ) , ZSTR_VAL ( constructor - > common . function_name ) , ZSTR_VAL ( scope - > name ) ) ;
constructor = NULL ;
} else {
zend_throw_error ( NULL , " Call to private %s::%s() from invalid context " , ZSTR_VAL ( constructor - > common . scope - > name ) , ZSTR_VAL ( constructor - > common . function_name ) ) ;
constructor = NULL ;
}
}
}
} else if ( ( constructor - > common . fn_flags & ZEND_ACC_PROTECTED ) ) {
/* Ensure that if we're calling a protected function, we're allowed to do so.
* Constructors only have prototype if they are defined by an interface but
* it is the compilers responsibility to take care of the prototype .
*/
if ( EG ( fake_scope ) ) {
scope = EG ( fake_scope ) ;
} else {
scope = zend_get_executed_scope ( ) ;
}
if ( UNEXPECTED ( ! zend_check_protected ( zend_get_function_root_class ( constructor ) , scope ) ) ) {
if ( scope ) {
zend_throw_error ( NULL , " Call to protected %s::%s() from context '%s' " , ZSTR_VAL ( constructor - > common . scope - > name ) , ZSTR_VAL ( constructor - > common . function_name ) , ZSTR_VAL ( scope - > name ) ) ;
constructor = NULL ;
} else {
zend_throw_error ( NULL , " Call to protected %s::%s() from invalid context " , ZSTR_VAL ( constructor - > common . scope - > name ) , ZSTR_VAL ( constructor - > common . function_name ) ) ;
constructor = NULL ;
ZEND_ASSERT ( constructor - > common . fn_flags & ZEND_ACC_PROTECTED ) ;
/* Ensure that if we're calling a protected function, we're allowed to do so.
* Constructors only have prototype if they are defined by an interface but
* it is the compilers responsibility to take care of the prototype .
*/
if ( UNEXPECTED ( ! zend_check_protected ( zend_get_function_root_class ( constructor ) , scope ) ) ) {
if ( scope ) {
zend_throw_error ( NULL , " Call to protected %s::%s() from context '%s' " , ZSTR_VAL ( constructor - > common . scope - > name ) , ZSTR_VAL ( constructor - > common . function_name ) , ZSTR_VAL ( scope - > name ) ) ;
constructor = NULL ;
} else {
zend_throw_error ( NULL , " Call to protected %s::%s() from invalid context " , ZSTR_VAL ( constructor - > common . scope - > name ) , ZSTR_VAL ( constructor - > common . function_name ) ) ;
constructor = NULL ;
}
}
}
}