cvs: ZendEngine2(PHP_5_3) / zend_object_handlers.c /tests bug48533.phpt php-src NEWS

[email protected] ("Felipe Pena") Fri, 12 Jun 2009 01:05:25 -0000
Newsgroups php.zend-engine.cvs
Message-ID <cvsfelipe1244768725@cvsserver>
--felipe1244768725
Content-Type: text/plain

felipe		Fri Jun 12 01:05:25 2009 UTC

  Added files:                 (Branch: PHP_5_3)
    /ZendEngine2/tests	bug48533.phpt 

  Modified files:              
    /php-src	NEWS 
    /ZendEngine2	zend_object_handlers.c 
  Log:
  MFH: Fixed bug #48533 (__callStatic is not invoked for private/protected methods)
  
  
--felipe1244768725
Content-Type: text/plain
Content-Disposition: attachment; filename="felipe-20090612010525.txt"

http://cvs.php.net/viewvc.cgi/php-src/NEWS?r1=1.2027.2.547.2.965.2.623&r2=1.2027.2.547.2.965.2.624&diff_format=u
Index: php-src/NEWS
diff -u php-src/NEWS:1.2027.2.547.2.965.2.623 php-src/NEWS:1.2027.2.547.2.965.2.624
--- php-src/NEWS:1.2027.2.547.2.965.2.623	Thu Jun 11 14:40:43 2009
+++ php-src/NEWS	Fri Jun 12 01:05:25 2009
@@ -3,6 +3,9 @@
 ?? ??? 2009, PHP 5.3.0 RC 4
 - Added phar.phar generation for Windows. (Greg)
 
+- Fixed bug #48533 (__callStatic is not invoked for private/protected methods).
+  (Felipe)
+
 11 Jun 2009, PHP 5.3.0 RC 3
 - Upgraded bundled sqlite to version 3.6.14.2. (Scott, Ilia)
 - Upgraded bundled libmagic to 5.03 in the fileinfo extension. (Scott)
http://cvs.php.net/viewvc.cgi/ZendEngine2/zend_object_handlers.c?r1=1.135.2.6.2.22.2.27&r2=1.135.2.6.2.22.2.28&diff_format=u
Index: ZendEngine2/zend_object_handlers.c
diff -u ZendEngine2/zend_object_handlers.c:1.135.2.6.2.22.2.27 ZendEngine2/zend_object_handlers.c:1.135.2.6.2.22.2.28
--- ZendEngine2/zend_object_handlers.c:1.135.2.6.2.22.2.27	Tue May 12 22:55:05 2009
+++ ZendEngine2/zend_object_handlers.c	Fri Jun 12 01:05:25 2009
@@ -17,7 +17,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: zend_object_handlers.c,v 1.135.2.6.2.22.2.27 2009/05/12 22:55:05 felipe Exp $ */
+/* $Id: zend_object_handlers.c,v 1.135.2.6.2.22.2.28 2009/06/12 01:05:25 felipe Exp $ */
 
 #include "zend.h"
 #include "zend_globals.h"
@@ -777,15 +777,15 @@
 }
 /* }}} */
 
-static inline union _zend_function *zend_get_user_call_function(zend_object *zobj, char *method_name, int method_len) /* {{{ */
+static inline union _zend_function *zend_get_user_call_function(zend_class_entry *ce, char *method_name, int method_len) /* {{{ */
 {
 	zend_internal_function *call_user_call = emalloc(sizeof(zend_internal_function));
 	call_user_call->type = ZEND_INTERNAL_FUNCTION;
-	call_user_call->module = zobj->ce->module;
+	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 = zobj->ce;
+	call_user_call->scope = ce;
 	call_user_call->fn_flags = ZEND_ACC_CALL_VIA_HANDLER;
 	call_user_call->function_name = estrndup(method_name, method_len);
 	call_user_call->pass_rest_by_reference = 0;
@@ -811,7 +811,7 @@
 	if (zend_hash_find(&zobj->ce->function_table, lc_method_name, method_len+1, (void **)&fbc) == FAILURE) {
 		free_alloca(lc_method_name, use_heap);
 		if (zobj->ce->__call) {
-			return zend_get_user_call_function(zobj, method_name, method_len);
+			return zend_get_user_call_function(zobj->ce, method_name, method_len);
 		} else {
 			return NULL;
 		}
@@ -829,7 +829,7 @@
 			fbc = updated_fbc;
 		} else {
 			if (zobj->ce->__call) {
-				fbc = zend_get_user_call_function(zobj, method_name, method_len);
+				fbc = zend_get_user_call_function(zobj->ce, method_name, method_len);
 			} 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), method_name, EG(scope) ? EG(scope)->name : "");
 			}
@@ -855,7 +855,7 @@
 			 */
 			if (!zend_check_protected(zend_get_function_root_class(fbc), EG(scope))) {
 				if (zobj->ce->__call) {
-					fbc = zend_get_user_call_function(zobj, method_name, method_len);
+					fbc = zend_get_user_call_function(zobj->ce, method_name, method_len);
 				} 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), method_name, EG(scope) ? EG(scope)->name : "");
 				}
@@ -912,6 +912,24 @@
 }
 /* }}} */
 
+static inline union _zend_function *zend_get_user_callstatic_function(zend_class_entry *ce, char *method_name, int method_len) /* {{{ */
+{
+	zend_internal_function *callstatic_user_call = emalloc(sizeof(zend_internal_function));
+	callstatic_user_call->type     = ZEND_INTERNAL_FUNCTION;
+	callstatic_user_call->module   = ce->module;
+	callstatic_user_call->handler  = zend_std_callstatic_user_call;
+	callstatic_user_call->arg_info = NULL;
+	callstatic_user_call->num_args = 0;
+	callstatic_user_call->scope    = ce;
+	callstatic_user_call->fn_flags = ZEND_ACC_STATIC | ZEND_ACC_PUBLIC | ZEND_ACC_CALL_VIA_HANDLER;
+	callstatic_user_call->function_name = estrndup(method_name, method_len);
+	callstatic_user_call->pass_rest_by_reference = 0;
+	callstatic_user_call->return_reference       = ZEND_RETURN_VALUE;
+
+	return (zend_function *)callstatic_user_call;
+}
+/* }}} */
+
 /* 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) /* {{{ */
@@ -935,35 +953,9 @@
 		    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 = ZEND_ACC_CALL_VIA_HANDLER;
-			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;
+			return zend_get_user_call_function(ce, function_name_strval, function_name_strlen);
 		} else if (ce->__callstatic) {
-			zend_internal_function *callstatic_user_call = emalloc(sizeof(zend_internal_function));
-
-			callstatic_user_call->type     = ZEND_INTERNAL_FUNCTION;
-			callstatic_user_call->module   = ce->module;
-			callstatic_user_call->handler  = zend_std_callstatic_user_call;
-			callstatic_user_call->arg_info = NULL;
-			callstatic_user_call->num_args = 0;
-			callstatic_user_call->scope    = ce;
-			callstatic_user_call->fn_flags = ZEND_ACC_STATIC | ZEND_ACC_PUBLIC | ZEND_ACC_CALL_VIA_HANDLER;
-			callstatic_user_call->function_name = estrndup(function_name_strval, function_name_strlen);
-			callstatic_user_call->pass_rest_by_reference = 0;
-			callstatic_user_call->return_reference       = ZEND_RETURN_VALUE;
-
-			return (zend_function *)callstatic_user_call;
+			return zend_get_user_callstatic_function(ce, function_name_strval, function_name_strlen);
 		} else {
 	   		return NULL;
 		}
@@ -985,14 +977,21 @@
 		/* Ensure that if we're calling a private function, we're allowed to do so.
 		 */
 		updated_fbc = zend_check_private_int(fbc, EG(scope), function_name_strval, function_name_strlen TSRMLS_CC);
-		if (!updated_fbc) {
+		if (updated_fbc) {
+			fbc = updated_fbc;
+		} else {
+			if (ce->__callstatic) {
+				return zend_get_user_callstatic_function(ce, function_name_strval, function_name_strlen);
+			}
 			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))) {
+			if (ce->__callstatic) {
+				return zend_get_user_callstatic_function(ce, function_name_strval, function_name_strlen);
+			}
 			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 : "");
 		}
 	}

http://cvs.php.net/viewvc.cgi/ZendEngine2/tests/bug48533.phpt?view=markup&rev=1.1
Index: ZendEngine2/tests/bug48533.phpt
+++ ZendEngine2/tests/bug48533.phpt
--TEST--
Bug #48533 (__callStatic is not invoked for private/protected methods)
--FILE--
<?php

class foo {
	private function a() {
		var_dump(1);	
	}
	public function b() {
		var_dump(2);
	}
	protected function c() {
		var_dump(3);
	}
	static function __callstatic($a, $b) {
		var_dump('__callStatic::'. $a);
	}
	public function __call($a, $b) {
		var_dump('__call::'. $a);
	}
}

$x = new foo;
$x->a();
$x->b();
$x->c();
$x::a();
$x::b();
$x::c();

?>
--EXPECTF--
%unicode|string%(9) "__call::a"
int(2)
%unicode|string%(9) "__call::c"
%unicode|string%(15) "__callStatic::a"

Strict Standards: Non-static method foo::b() should not be called statically in %s on line %d
int(2)
%unicode|string%(15) "__callStatic::c"

--felipe1244768725--