Hi internals,
It seems that there is a bug in the way some callbacks are handled. For
instance:
array('B', 'parent::who');
Here, the classname 'B' will only be used for inheritance checks with
the current scope,
but the actual resolution will be made using the current scope, and
'parent::who'.
According to Marcus, this is wrong, so here is two patches (+ tests)
meant for HEAD [1]
and the 5_2 branch (>5.2.3) [2].
Thanks for your consideration.
Regards
1: http://patches.colder.ch/Zend/callbacks_HEAD.patch?markup
2: http://patches.colder.ch/Zend/callbacks_5_2.patch?markup
--
Etienne Kneuss
http://www.colder.ch
[EMAIL PROTECTED]
Men never do evil so completely and cheerfully as
when they do it from a religious conviction.
-- Pascal
Index: ext/standard/tests/general_functions/callbacks_001.phpt
===================================================================
RCS file: ext/standard/tests/general_functions/callbacks_001.phpt
diff -N ext/standard/tests/general_functions/callbacks_001.phpt
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ext/standard/tests/general_functions/callbacks_001.phpt 27 May 2007
21:38:48 -0000
@@ -0,0 +1,55 @@
+--TEST--
+ZE2 Callbacks of static functions
+--FILE--
+<?php
+class A {
+ public static function who() {
+ echo "A\n";
+ }
+ public static function who2() {
+ echo "A\n";
+ }
+}
+
+class B extends A {
+ public static function who() {
+ echo "B\n";
+ }
+}
+class C extends B {
+ public function foo() {
+ call_user_func(array('parent', 'who'));
+ call_user_func(array('C', 'parent::who'));
+ call_user_func(array('B', 'parent::who'));
+ call_user_func(array('E', 'parent::who'));
+ call_user_func(array('B', 'who2'));
+ call_user_func(array('A', 'who'));
+ call_user_func(array('C', 'who'));
+ }
+}
+
+class D {
+ public static function who() {
+ echo "D\n";
+ }
+}
+
+class E extends D {
+ public static function who() {
+ echo "E\n";
+ }
+}
+
+$o = new C;
+$o->foo();
+?>
+===DONE===
+--EXPECT--
+B
+B
+A
+D
+A
+A
+B
+===DONE===
Index: Zend/zend_API.c
===================================================================
RCS file: /repository/ZendEngine2/zend_API.c,v
retrieving revision 1.296.2.27.2.30
diff -u -r1.296.2.27.2.30 zend_API.c
--- Zend/zend_API.c 16 May 2007 18:57:15 -0000 1.296.2.27.2.30
+++ Zend/zend_API.c 27 May 2007 21:38:50 -0000
@@ -2125,6 +2125,8 @@
mlen = Z_STRLEN_P(callable) - clen - 2;
lcname = zend_str_tolower_dup(Z_STRVAL_P(callable), clen);
/* caution: lcname is not '\0' terminated */
+ zend_class_entry *last_scope = EG(scope);
+ EG(scope) = ce_org;
if (clen == sizeof("self") - 1 && memcmp(lcname, "self",
sizeof("self") - 1) == 0) {
*ce_ptr = EG(scope);
} else if (clen == sizeof("parent") - 1 && memcmp(lcname,
"parent", sizeof("parent") - 1) == 0 && EG(active_op_array)->scope) {
@@ -2132,6 +2134,7 @@
} else if (zend_lookup_class(Z_STRVAL_P(callable), clen, &pce
TSRMLS_CC) == SUCCESS) {
*ce_ptr = *pce;
}
+ EG(scope) = last_scope;
efree(lcname);
if (!*ce_ptr) {
return 0;
Index: Zend/zend_execute_API.c
===================================================================
RCS file: /repository/ZendEngine2/zend_execute_API.c,v
retrieving revision 1.331.2.20.2.19
diff -u -r1.331.2.20.2.19 zend_execute_API.c
--- Zend/zend_execute_API.c 27 Apr 2007 08:12:24 -0000 1.331.2.20.2.19
+++ Zend/zend_execute_API.c 27 May 2007 21:38:53 -0000
@@ -750,7 +750,8 @@
if ((colon = strstr(fname, "::")) != NULL) {
int clen = colon - fname;
int mlen = fname_len - clen - 2;
- zend_class_entry **pce, *ce_child = NULL;
+ zend_class_entry **pce, *ce_child = NULL, *last_scope =
EG(scope);
+ EG(scope) = calling_scope;
if (zend_lookup_class(fname, clen, &pce TSRMLS_CC) ==
SUCCESS) {
ce_child = *pce;
} else {
@@ -765,6 +766,7 @@
}
efree(lcname);
}
+ EG(scope) = last_scope;
if (!ce_child) {
zend_error(E_ERROR, "Cannot call method %s() or
method does not exist", fname);
return FAILURE;
Index: Zend/zend_API.c
===================================================================
RCS file: /repository/ZendEngine2/zend_API.c,v
retrieving revision 1.433
diff -u -r1.433 zend_API.c
--- Zend/zend_API.c 16 May 2007 18:56:38 -0000 1.433
+++ Zend/zend_API.c 27 May 2007 15:31:44 -0000
@@ -2561,7 +2561,11 @@
}
}
if (colon.v != NULL) {
+ zend_class_entry *last_scope = EG(scope);
+ EG(scope) = ce_org;
*ce_ptr = zend_u_fetch_class(Z_TYPE_P(callable),
Z_UNIVAL_P(callable), clen, ZEND_FETCH_CLASS_AUTO TSRMLS_CC);
+ EG(scope) = last_scope;
+
if (!*ce_ptr) {
return 0;
}
Index: ext/standard/tests/general_functions/callbacks_001.phpt
===================================================================
RCS file: ext/standard/tests/general_functions/callbacks_001.phpt
diff -N ext/standard/tests/general_functions/callbacks_001.phpt
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ext/standard/tests/general_functions/callbacks_001.phpt 27 May 2007
15:31:44 -0000
@@ -0,0 +1,55 @@
+--TEST--
+ZE2 Callbacks of static functions
+--FILE--
+<?php
+class A {
+ public static function who() {
+ echo "A\n";
+ }
+ public static function who2() {
+ echo "A\n";
+ }
+}
+
+class B extends A {
+ public static function who() {
+ echo "B\n";
+ }
+}
+class C extends B {
+ public function foo() {
+ call_user_func(array('parent', 'who'));
+ call_user_func(array('C', 'parent::who'));
+ call_user_func(array('B', 'parent::who'));
+ call_user_func(array('E', 'parent::who'));
+ call_user_func(array('B', 'who2'));
+ call_user_func(array('A', 'who'));
+ call_user_func(array('C', 'who'));
+ }
+}
+
+class D {
+ public static function who() {
+ echo "D\n";
+ }
+}
+
+class E extends D {
+ public static function who() {
+ echo "E\n";
+ }
+}
+
+$o = new C;
+$o->foo();
+?>
+===DONE===
+--EXPECT--
+B
+B
+A
+D
+A
+A
+B
+===DONE===
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php