All pastes #1305898 Raw Edit

rewbs

public diff v1 · immutable
#1305898 ·published 2009-01-11 12:44 UTC
rendered paste body
Index: Zend/zend_object_handlers.c===================================================================RCS file: /repository/ZendEngine2/zend_object_handlers.c,vretrieving revision 1.135.2.6.2.31diff -u -w -p -r1.135.2.6.2.31 zend_object_handlers.c--- Zend/zend_object_handlers.c	8 Jan 2009 00:39:15 -0000	1.135.2.6.2.31+++ Zend/zend_object_handlers.c	11 Jan 2009 12:33:05 -0000@@ -849,33 +849,29 @@ static union _zend_function *zend_std_ge }  +/* Checks whether __call() should be used in the case where a method invocation has+ * been made using the Scope Resolution Operator (::), but the method was not found+ * or is not visible. */+static inline int zend_use_user_call_with_SRO(zend_class_entry *ce TSRMLS_DC) /* {{{ */+{+	// Return true if the target class has a __call() method and+	// the current object context is compatible with the target class. +	return ce->__call &&+           EG(This) &&+           Z_OBJ_HT_P(EG(This))->get_class_entry &&+           instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC);+}+ /* This is not (yet?) in the API, but it belongs in the built-in objects callbacks */ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, char *function_name_strval, int function_name_strlen TSRMLS_DC) { 	zend_function *fbc;  	if (zend_hash_find(&ce->function_table, function_name_strval, function_name_strlen+1, (void **) &fbc)==FAILURE) {-		if (ce->__call &&-		    EG(This) &&-		    Z_OBJ_HT_P(EG(This))->get_class_entry &&-		    instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) {-			zend_internal_function *call_user_call = emalloc(sizeof(zend_internal_function));--			call_user_call->type = ZEND_INTERNAL_FUNCTION;-			call_user_call->module = ce->module;-			call_user_call->handler = zend_std_call_user_call;-			call_user_call->arg_info = NULL;-			call_user_call->num_args = 0;-			call_user_call->scope = ce;-			call_user_call->fn_flags = 0;-			call_user_call->function_name = estrndup(function_name_strval, function_name_strlen);-			call_user_call->pass_rest_by_reference = 0;-			call_user_call->return_reference = ZEND_RETURN_VALUE;--			return (union _zend_function *)call_user_call;+		if (zend_use_user_call_with_SRO(ce TSRMLS_CC)) {			+			return zend_get_user_call_function(Z_OBJ_P(EG(This)), function_name_strval, function_name_strlen); 		} else { 			char *class_name = ce->name;- 			if (!class_name) { 				class_name = ""; 			}@@ -891,13 +887,19 @@ ZEND_API zend_function *zend_std_get_sta 		 */ 		updated_fbc = zend_check_private_int(fbc, EG(scope), function_name_strval, function_name_strlen TSRMLS_CC); 		if (!updated_fbc) {+			if (zend_use_user_call_with_SRO(ce TSRMLS_CC)) {			+                return zend_get_user_call_function(Z_OBJ_P(EG(This)), function_name_strval, function_name_strlen);+			} else {			 			zend_error(E_ERROR, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), function_name_strval, EG(scope) ? EG(scope)->name : ""); 		}+		} 		fbc = updated_fbc; 	} else if ((fbc->common.fn_flags & ZEND_ACC_PROTECTED)) { 		/* Ensure that if we're calling a protected function, we're allowed to do so. 		 */ 		if (!zend_check_protected(zend_get_function_root_class(fbc), EG(scope))) {+			// No need to check zend_use_user_call_with_SRO(): if the protected method isn't visible,+			// the scopes are not compatible, so we will not fall back to __call(). 			zend_error(E_ERROR, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), function_name_strval, EG(scope) ? EG(scope)->name : ""); 		} 	}Index: Zend/tests/access_modifiers_013.phpt===================================================================RCS file: Zend/tests/access_modifiers_013.phptdiff -N Zend/tests/access_modifiers_013.phpt--- /dev/null	1 Jan 1970 00:00:00 -0000+++ Zend/tests/access_modifiers_013.phpt	11 Jan 2009 11:27:55 -0000@@ -0,0 +1,22 @@+--TEST--+Trigger __call() when attempting to access a private in parent with scope resolution operator.+--FILE--+<?php+Class C {+    private function priv() {}+    function __call($name, $args) { echo "In C::__call($name)\n"; }+}++class D extends C {+  function test() {+    C::none();+    C::priv();+  }+}++$d = new D;+$d->test();+?>+--EXPECTF--+In C::__call(none)+In C::__call(priv)\ No newline at end of file