Hi all. The patch fixes bug #29210 perfectly, but I'm not sure if the implementation is the best. The appropriate test is attached too.
Any comments are welcome. --- WBR, Antony Dovgal aka tony2001 [EMAIL PROTECTED] || [EMAIL PROTECTED]
Index: zend_API.c =================================================================== RCS file: /repository/ZendEngine2/zend_API.c,v retrieving revision 1.256 diff -u -r1.256 zend_API.c --- zend_API.c 5 Jun 2004 14:59:21 -0000 1.256 +++ zend_API.c 5 Aug 2004 11:48:04 -0000 @@ -1721,10 +1721,47 @@ } if (ce) { + zend_function *fbc; + zend_object *zobj; + zval tmp_obj; + + if (Z_TYPE_PP(obj) == IS_OBJECT) { + zobj = zend_objects_get_address(*obj TSRMLS_CC); + tmp_obj = **obj; + } + else { + tmp_obj.value.obj = zend_objects_new(&zobj, ce TSRMLS_CC); + ALLOC_HASHTABLE(zobj->properties); + zend_hash_init(zobj->properties, 0, NULL, ZVAL_PTR_DTOR, 0); + } + lcname = zend_str_tolower_dup(Z_STRVAL_PP(method), Z_STRLEN_PP(method)); - if (zend_hash_exists(&ce->function_table, lcname, Z_STRLEN_PP(method)+1)) { - retval = 1; + + retval = 1; + + if (zend_hash_find(&zobj->ce->function_table, lcname, Z_STRLEN_PP(method)+1, (void **)&fbc) == SUCCESS) { + if (fbc->op_array.fn_flags & ZEND_ACC_PUBLIC) { + if (EG(scope) && fbc->op_array.fn_flags & ZEND_ACC_CHANGED) { + zend_function *priv_fbc; + + if (zend_hash_find(&EG(scope)->function_table, lcname, Z_STRLEN_PP(method)+1, (void **) &priv_fbc)==SUCCESS + && priv_fbc->common.fn_flags & ZEND_ACC_PRIVATE) { + retval = 0; + } + } + } else if (fbc->op_array.fn_flags & ZEND_ACC_PRIVATE) { + + if (!zend_check_private(fbc, tmp_obj.value.obj.handlers->get_class_entry(&tmp_obj TSRMLS_CC), fbc->common.fn_flags, lcname, Z_STRLEN_PP(method) TSRMLS_CC)) { + retval = 0; + } + } else if ((fbc->common.fn_flags & ZEND_ACC_PROTECTED)) { + if (!zend_check_protected(fbc->common.scope, EG(scope))) { + retval = 0; + } + } + } + /* check for __call too */ if (retval == 0 && ce->__call != 0) { retval = 1; Index: zend_object_handlers.c =================================================================== RCS file: /repository/ZendEngine2/zend_object_handlers.c,v retrieving revision 1.104 diff -u -r1.104 zend_object_handlers.c --- zend_object_handlers.c 22 Jul 2004 11:54:27 -0000 1.104 +++ zend_object_handlers.c 5 Aug 2004 11:48:04 -0000 @@ -601,7 +601,7 @@ * Returns the function address that should be called, or NULL * if no such function exists. */ -inline zend_function *zend_check_private(zend_function *fbc, zend_class_entry *ce, int fn_flags, char *function_name_strval, int function_name_strlen TSRMLS_DC) +ZEND_API inline zend_function *zend_check_private(zend_function *fbc, zend_class_entry *ce, int fn_flags, char *function_name_strval, int function_name_strlen TSRMLS_DC) { if (!ce) { return 0; Index: zend_object_handlers.h =================================================================== RCS file: /repository/ZendEngine2/zend_object_handlers.h,v retrieving revision 1.41 diff -u -r1.41 zend_object_handlers.h --- zend_object_handlers.h 4 May 2004 15:03:28 -0000 1.41 +++ zend_object_handlers.h 5 Aug 2004 11:48:04 -0000 @@ -137,6 +137,8 @@ #define IS_ZEND_STD_OBJECT(z) ((z).type == IS_OBJECT && (Z_OBJ_HT((z))->get_class_entry != NULL)) #define HAS_CLASS_ENTRY(z) (Z_OBJ_HT(z)->get_class_entry != NULL) +ZEND_API inline union _zend_function *zend_check_private(union _zend_function *fbc, zend_class_entry *ce, int fn_flags, char *function_name_strval, int function_name_strlen TSRMLS_CC); + ZEND_API int zend_check_protected(zend_class_entry *ce, zend_class_entry *scope); ZEND_API int zend_check_property_access(zend_object *zobj, char *prop_info_name TSRMLS_DC);
--TEST-- is_callable() with public/private/protected methods --FILE-- <?php /* $Id: zend_operators.phpt,v 1.1 2004/03/04 10:58:49 derick Exp $ */ class Test { public function foo() { echo "Private IS callable from the class (yes): "; echo ", static: "; echo is_callable(array('test','bar')) ? "yes\n" : "no\n"; } private function bar() { } protected function pro() { } } class Test2 extends Test { public function boo() { echo "Private IS NOT callable from the derived class (no): "; echo is_callable(array($this,'bar')) ? "yes" : "no"; echo ", static: "; echo is_callable(array('test','bar')) ? "yes\n" : "no\n"; echo "Public IS callable from the derived class (yes): "; echo is_callable(array($this,'foo')) ? "yes" : "no"; echo ", static: "; echo is_callable(array('test','foo')) ? "yes\n" : "no\n"; echo "Protected IS callable from the derived class (yes): "; echo is_callable(array($this,'pro')) ? "yes" : "no"; echo ", static: "; echo is_callable(array('test','pro')) ? "yes\n" : "no\n"; } } $test = new Test; echo "Public IS callable from outside the class (yes): "; echo is_callable(array($test,'foo')) ? "yes" : "no"; echo ", static: "; echo is_callable(array('test','foo')) ? "yes\n" : "no\n"; echo "Private IS NOT callable from outside the class (no): "; echo is_callable(array($test,'bar')) ? "yes" : "no"; echo ", static: "; echo is_callable(array('test','bar')) ? "yes\n" : "no\n"; echo "Protected IS NOT callable from outside the class (no): "; echo is_callable(array($test,'pro')) ? "yes" : "no"; echo ", static: "; echo is_callable(array('test','pro')) ? "yes\n" : "no\n"; $test->foo(); $test2 = new Test2; $test2->boo(); ?> --EXPECT-- Public IS callable from outside the class (yes): yes, static: yes Private IS NOT callable from outside the class (no): no, static: no Protected IS NOT callable from outside the class (no): no, static: no Private IS callable from the class (yes): , static: yes Private IS NOT callable from the derived class (no): no, static: no Public IS callable from the derived class (yes): yes, static: yes Protected IS callable from the derived class (yes): yes, static: yes
-- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php