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