From: Felipe Pena Date: Fri, 22 Aug 2008 01:06:55 +0000 (+0000) Subject: MFH: X-Git-Tag: php-5.2.7RC1~87 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ebdf8d3637a6e3d4c21e96172576f0bd179aa469;p=php MFH: - Fixed bug #45862 (get_class_vars is inconsistent with 'protected' and 'private' variables) - Added some tests --- diff --git a/NEWS b/NEWS index 0916f62001..301598f96e 100644 --- a/NEWS +++ b/NEWS @@ -19,6 +19,8 @@ PHP NEWS - Fixed a crash on invalid method in ReflectionParameter constructor. (Christian Seiler) +- Fixed bug #45862 (get_class_vars is inconsistent with 'protected' and + 'private' variables). (ilewis at uk dot ibm dot com, Felipe) - Fixed bug #45805 (Crash on throwing exception from error handler). (Dmitry) - Fixed bug #45765 (ReflectionObject with default parameters of self::xxx cause an error). (Felipe) diff --git a/Zend/tests/bug45862.phpt b/Zend/tests/bug45862.phpt new file mode 100644 index 0000000000..f70c14234c --- /dev/null +++ b/Zend/tests/bug45862.phpt @@ -0,0 +1,43 @@ +--TEST-- +Bug #45862 (get_class_vars is inconsistent with 'protected' and 'private' variables) +--FILE-- +test(); +echo "\n From child scope\n"; +$child = new Child(); +$child->test(); + +?> +--EXPECT-- + + From parent scope +array(1) { + ["prot"]=> + string(13) "protected var" +} +string(13) "protected var" + + From child scope +array(1) { + ["prot"]=> + string(13) "protected var" +} diff --git a/Zend/tests/get_class_vars_001.phpt b/Zend/tests/get_class_vars_001.phpt new file mode 100644 index 0000000000..ada0be6dad --- /dev/null +++ b/Zend/tests/get_class_vars_001.phpt @@ -0,0 +1,33 @@ +--TEST-- +get_class_vars(): Simple test +--FILE-- + +--EXPECT-- +array(1) { + ["a"]=> + int(1) +} +array(2) { + ["a"]=> + int(1) + ["aa"]=> + int(4) +} diff --git a/Zend/tests/get_class_vars_002.phpt b/Zend/tests/get_class_vars_002.phpt new file mode 100644 index 0000000000..721ebe692e --- /dev/null +++ b/Zend/tests/get_class_vars_002.phpt @@ -0,0 +1,49 @@ +--TEST-- +get_class_vars(): Testing the scope +--FILE-- +a, $this->b, $this->c); + } +} + +new C; + +?> +--EXPECTF-- +array(1) { + ["a"]=> + int(1) +} +array(3) { + ["a"]=> + int(1) + ["aa"]=> + int(4) + ["cc"]=> + int(6) +} + +Notice: Undefined property: C::$b in %s on line %d + +Notice: Undefined property: C::$c in %s on line %d +int(1) +NULL +NULL diff --git a/Zend/tests/get_class_vars_003.phpt b/Zend/tests/get_class_vars_003.phpt new file mode 100644 index 0000000000..f9dab77c2f --- /dev/null +++ b/Zend/tests/get_class_vars_003.phpt @@ -0,0 +1,47 @@ +--TEST-- +get_class_vars(): Testing the scope +--FILE-- + +--EXPECT-- +array(5) { + ["aaa"]=> + int(7) + ["ccc"]=> + int(9) + ["a"]=> + int(1) + ["aa"]=> + int(4) + ["cc"]=> + int(6) +} diff --git a/Zend/tests/get_class_vars_004.phpt b/Zend/tests/get_class_vars_004.phpt new file mode 100644 index 0000000000..26cd461ba4 --- /dev/null +++ b/Zend/tests/get_class_vars_004.phpt @@ -0,0 +1,67 @@ +--TEST-- +get_class_vars(): Testing the scope +--FILE-- + +--EXPECT-- +array(2) { + ["a"]=> + int(1) + ["A"]=> + int(2) +} +array(6) { + ["a"]=> + int(1) + ["b"]=> + int(3) + ["c"]=> + int(5) + ["A"]=> + int(2) + ["B"]=> + int(4) + ["C"]=> + int(6) +} +array(6) { + ["a"]=> + int(1) + ["b"]=> + int(3) + ["c"]=> + int(5) + ["A"]=> + int(2) + ["B"]=> + int(4) + ["C"]=> + int(6) +} +NULL diff --git a/Zend/tests/get_class_vars_005.phpt b/Zend/tests/get_class_vars_005.phpt new file mode 100644 index 0000000000..51f54900a9 --- /dev/null +++ b/Zend/tests/get_class_vars_005.phpt @@ -0,0 +1,39 @@ +--TEST-- +get_class_vars(): Testing visibility +--FILE-- + +--EXPECT-- +array(0) { +} +array(0) { +} +array(1) { + ["a"]=> + int(1) +} +array(2) { + ["c"]=> + int(3) + ["a"]=> + int(1) +} diff --git a/Zend/tests/get_class_vars_006.phpt b/Zend/tests/get_class_vars_006.phpt new file mode 100644 index 0000000000..73de66ba98 --- /dev/null +++ b/Zend/tests/get_class_vars_006.phpt @@ -0,0 +1,48 @@ +--TEST-- +get_class_vars(): Testing visibility +--FILE-- + +--EXPECT-- +array(0) { +} +array(0) { +} +array(0) { +} +--- +array(1) { + ["a"]=> + int(1) +} +array(1) { + ["a"]=> + int(1) +} +array(0) { +} diff --git a/Zend/tests/get_class_vars_007.phpt b/Zend/tests/get_class_vars_007.phpt new file mode 100644 index 0000000000..6aea0e2483 --- /dev/null +++ b/Zend/tests/get_class_vars_007.phpt @@ -0,0 +1,41 @@ +--TEST-- +get_class_vars(): Testing with static properties +--FILE-- + +--EXPECT-- +array(2) { + ["a"]=> + NULL + ["aa"]=> + NULL +} +array(6) { + ["a"]=> + NULL + ["aa"]=> + NULL + ["b"]=> + NULL + ["bb"]=> + NULL + ["c"]=> + NULL + ["cc"]=> + NULL +} +NULL diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index bd84c263f1..830bcf39d4 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -710,8 +710,6 @@ ZEND_FUNCTION(is_a) /* {{{ add_class_vars */ static void add_class_vars(zend_class_entry *ce, HashTable *properties, zval *return_value TSRMLS_DC) { - int instanceof = EG(scope) && instanceof_function(EG(scope), ce TSRMLS_CC); - if (zend_hash_num_elements(properties) > 0) { HashPosition pos; zval **prop; @@ -720,20 +718,28 @@ static void add_class_vars(zend_class_entry *ce, HashTable *properties, zval *re while (zend_hash_get_current_data_ex(properties, (void **) &prop, &pos) == SUCCESS) { char *key, *class_name, *prop_name; uint key_len; - ulong num_index; + ulong num_index, h; + int prop_name_len = 0; zval *prop_copy; + zend_property_info *property_info; zend_hash_get_current_key_ex(properties, &key, &key_len, &num_index, 0, &pos); zend_hash_move_forward_ex(properties, &pos); + zend_unmangle_property_name(key, key_len-1, &class_name, &prop_name); - if (class_name) { - if (class_name[0] != '*' && strcmp(class_name, ce->name)) { - /* filter privates from base classes */ - continue; - } else if (!instanceof) { - /* filter protected if not inside class */ - continue; - } + prop_name_len = strlen(prop_name); + + h = zend_get_hash_value(prop_name, prop_name_len+1); + if (zend_hash_quick_find(&ce->properties_info, prop_name, prop_name_len+1, h, (void **) &property_info) == FAILURE) { + continue; + } + + if (property_info->flags & ZEND_ACC_SHADOW) { + continue; + } else if ((property_info->flags & ZEND_ACC_PRIVATE) && EG(scope) != ce) { + continue; + } else if ((property_info->flags & ZEND_ACC_PROTECTED) && zend_check_protected(ce, EG(scope)) == 0) { + continue; } /* copy: enforce read only access */