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

Reply via email to