@@ -1055,11 +1055,34 @@ ZEND_API void zend_std_unset_dimension(zval *object, zval *offset) /* {{{ */
1055
1055
}
1056
1056
/* }}} */
1057
1057
1058
+ static zend_always_inline zend_function * zend_get_parent_private (zend_class_entry * scope , zend_class_entry * ce , zend_string * function_name ) /* {{{ */
1059
+ {
1060
+ zval * func ;
1061
+ zend_function * fbc ;
1062
+
1063
+ ce = ce -> parent ;
1064
+ while (ce ) {
1065
+ if (ce == scope ) {
1066
+ if ((func = zend_hash_find (& ce -> function_table , function_name ))) {
1067
+ fbc = Z_FUNC_P (func );
1068
+ if (fbc -> common .fn_flags & ZEND_ACC_PRIVATE
1069
+ && fbc -> common .scope == scope ) {
1070
+ return fbc ;
1071
+ }
1072
+ }
1073
+ break ;
1074
+ }
1075
+ ce = ce -> parent ;
1076
+ }
1077
+ return NULL ;
1078
+ }
1079
+ /* }}} */
1080
+
1058
1081
/* Ensures that we're allowed to call a private method.
1059
1082
* Returns the function address that should be called, or NULL
1060
1083
* if no such function exists.
1061
1084
*/
1062
- static inline zend_function * zend_check_private_int (zend_function * fbc , zend_class_entry * ce , zend_string * function_name ) /* {{{ */
1085
+ ZEND_API int zend_check_private (zend_function * fbc , zend_class_entry * ce , zend_string * function_name ) /* {{{ */
1063
1086
{
1064
1087
zval * func ;
1065
1088
zend_class_entry * scope ;
@@ -1077,32 +1100,12 @@ static inline zend_function *zend_check_private_int(zend_function *fbc, zend_cla
1077
1100
scope = zend_get_executed_scope ();
1078
1101
if (fbc -> common .scope == ce && scope == ce ) {
1079
1102
/* rule #1 checks out ok, allow the function call */
1080
- return fbc ;
1103
+ return 1 ;
1081
1104
}
1082
1105
1083
1106
1084
1107
/* Check rule #2 */
1085
- ce = ce -> parent ;
1086
- while (ce ) {
1087
- if (ce == scope ) {
1088
- if ((func = zend_hash_find (& ce -> function_table , function_name ))) {
1089
- fbc = Z_FUNC_P (func );
1090
- if (fbc -> common .fn_flags & ZEND_ACC_PRIVATE
1091
- && fbc -> common .scope == scope ) {
1092
- return fbc ;
1093
- }
1094
- }
1095
- break ;
1096
- }
1097
- ce = ce -> parent ;
1098
- }
1099
- return NULL ;
1100
- }
1101
- /* }}} */
1102
-
1103
- ZEND_API int zend_check_private (zend_function * fbc , zend_class_entry * ce , zend_string * function_name ) /* {{{ */
1104
- {
1105
- return zend_check_private_int (fbc , ce , function_name ) != NULL ;
1108
+ return zend_get_parent_private (scope , ce , function_name ) != NULL ;
1106
1109
}
1107
1110
/* }}} */
1108
1111
@@ -1218,21 +1221,22 @@ ZEND_API zend_function *zend_std_get_method(zend_object **obj_ptr, zend_string *
1218
1221
fbc = Z_FUNC_P (func );
1219
1222
/* Check access level */
1220
1223
if (fbc -> op_array .fn_flags & ZEND_ACC_PRIVATE ) {
1221
- zend_function * updated_fbc ;
1222
-
1223
1224
/* Ensure that if we're calling a private function, we're allowed to do so.
1224
1225
* If we're not and __call() handler exists, invoke it, otherwise error out.
1225
1226
*/
1226
- updated_fbc = zend_check_private_int (fbc , zobj -> ce , lc_method_name );
1227
- if (EXPECTED (updated_fbc != NULL )) {
1228
- fbc = updated_fbc ;
1229
- } else {
1230
- if (zobj -> ce -> __call ) {
1231
- fbc = zend_get_user_call_function (zobj -> ce , method_name );
1227
+ scope = zend_get_executed_scope ();
1228
+ if (fbc -> common .scope != scope || zobj -> ce != scope ) {
1229
+ zend_function * updated_fbc = zend_get_parent_private (scope , zobj -> ce , lc_method_name );
1230
+ if (EXPECTED (updated_fbc != NULL )) {
1231
+ fbc = updated_fbc ;
1232
1232
} else {
1233
- scope = zend_get_executed_scope ();
1234
- zend_throw_error (NULL , "Call to %s method %s::%s() from context '%s'" , zend_visibility_string (fbc -> common .fn_flags ), ZEND_FN_SCOPE_NAME (fbc ), ZSTR_VAL (method_name ), scope ? ZSTR_VAL (scope -> name ) : "" );
1235
- fbc = NULL ;
1233
+ if (zobj -> ce -> __call ) {
1234
+ fbc = zend_get_user_call_function (zobj -> ce , method_name );
1235
+ } else {
1236
+ scope = zend_get_executed_scope ();
1237
+ zend_throw_error (NULL , "Call to %s method %s::%s() from context '%s'" , zend_visibility_string (fbc -> common .fn_flags ), ZEND_FN_SCOPE_NAME (fbc ), ZSTR_VAL (method_name ), scope ? ZSTR_VAL (scope -> name ) : "" );
1238
+ fbc = NULL ;
1239
+ }
1236
1240
}
1237
1241
}
1238
1242
} else if (fbc -> op_array .fn_flags & (ZEND_ACC_CHANGED |ZEND_ACC_PROTECTED )) {
@@ -1242,14 +1246,9 @@ ZEND_API zend_function *zend_std_get_method(zend_object **obj_ptr, zend_string *
1242
1246
1243
1247
scope = zend_get_executed_scope ();
1244
1248
if (fbc -> op_array .fn_flags & ZEND_ACC_CHANGED ) {
1245
- if (scope && is_derived_class (fbc -> common .scope , scope )) {
1246
- if ((func = zend_hash_find (& scope -> function_table , lc_method_name )) != NULL ) {
1247
- zend_function * priv_fbc = Z_FUNC_P (func );
1248
- if (priv_fbc -> common .fn_flags & ZEND_ACC_PRIVATE
1249
- && priv_fbc -> common .scope == scope ) {
1250
- fbc = priv_fbc ;
1251
- }
1252
- }
1249
+ zend_function * priv_fbc = zend_get_parent_private (scope , fbc -> common .scope , lc_method_name );
1250
+ if (priv_fbc ) {
1251
+ fbc = priv_fbc ;
1253
1252
}
1254
1253
} else {
1255
1254
/* Ensure that if we're calling a protected function, we're allowed to do so.
@@ -1339,15 +1338,10 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_st
1339
1338
if (fbc -> op_array .fn_flags & ZEND_ACC_PUBLIC ) {
1340
1339
/* No further checks necessary, most common case */
1341
1340
} else if (fbc -> op_array .fn_flags & ZEND_ACC_PRIVATE ) {
1342
- zend_function * updated_fbc ;
1343
-
1344
1341
/* Ensure that if we're calling a private function, we're allowed to do so.
1345
1342
*/
1346
1343
scope = zend_get_executed_scope ();
1347
- updated_fbc = zend_check_private_int (fbc , scope , lc_function_name );
1348
- if (EXPECTED (updated_fbc != NULL )) {
1349
- fbc = updated_fbc ;
1350
- } else {
1344
+ if (UNEXPECTED (fbc -> common .scope != scope )) {
1351
1345
if (ce -> __callstatic ) {
1352
1346
fbc = zend_get_user_callstatic_function (ce , function_name );
1353
1347
} else {
0 commit comments