From ec79b63d694423e69418517c93b0b77b1c32de3b Mon Sep 17 00:00:00 2001 From: Antony Dovgal Date: Sat, 10 Feb 2007 20:51:42 +0000 Subject: [PATCH] fix #40431 (dynamic properties may cause crash in ReflectionProperty methods) --- ext/reflection/php_reflection.c | 11 +- ext/reflection/tests/bug40431.phpt | 198 +++++++++++++++++++++++++++++ 2 files changed, 206 insertions(+), 3 deletions(-) create mode 100644 ext/reflection/tests/bug40431.phpt diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index d1673f882e..fd88216028 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -1155,15 +1155,20 @@ static void reflection_property_factory(zend_class_entry *ce, zend_property_info if (!(prop->flags & ZEND_ACC_PRIVATE)) { /* we have to search the class hierarchy for this (implicit) public or protected property */ - zend_class_entry *tmp_ce = ce; - zend_property_info *tmp_info; + zend_class_entry *tmp_ce = ce, *store_ce = ce; + zend_property_info *tmp_info = NULL; int prop_name_len = UG(unicode) ? u_strlen(prop_name.u) : strlen(prop_name.s); while (tmp_ce && zend_u_hash_find(&tmp_ce->properties_info, utype, prop_name, prop_name_len + 1, (void **) &tmp_info) != SUCCESS) { ce = tmp_ce; - prop = tmp_info; tmp_ce = tmp_ce->parent; } + + if (tmp_info && !(tmp_info->flags & ZEND_ACC_SHADOW)) { /* found something and it's not a parent's private */ + prop = tmp_info; + } else { /* not found, use initial value */ + ce = store_ce; + } } MAKE_STD_ZVAL(name); diff --git a/ext/reflection/tests/bug40431.phpt b/ext/reflection/tests/bug40431.phpt new file mode 100644 index 0000000000..68c18cf0d4 --- /dev/null +++ b/ext/reflection/tests/bug40431.phpt @@ -0,0 +1,198 @@ +--TEST-- +Bug #40431 (dynamic properties may cause crash in ReflectionProperty methods) +--FILE-- +value = 'value'; +$RefObj = new ReflectionObject($Obj); + +$props = $RefObj->getProperties(); + +var_dump($props); +var_dump($props[0]->isStatic()); +var_dump($props[0]->isPrivate()); +var_dump($props[0]->isPublic()); +var_dump($props[0]->isProtected()); + +echo "=== 2nd test ===\n"; + +class test1 { +} + +class test2 extends test1{ +} + +$Obj = new test2; +$Obj->value = 'value'; +$RefObj = new ReflectionObject($Obj); + +$props = $RefObj->getProperties(); + +var_dump($props); +var_dump($props[0]->isStatic()); +var_dump($props[0]->isPrivate()); +var_dump($props[0]->isPublic()); +var_dump($props[0]->isProtected()); + +echo "=== 3rd test ===\n"; + +class test3 { +} + +$Obj = new test3; +$Obj->value = 'value'; +$RefObj = new ReflectionObject($Obj); + +$props = $RefObj->getProperties(); + +var_dump($props); +var_dump($props[0]->isStatic()); +var_dump($props[0]->isPrivate()); +var_dump($props[0]->isPublic()); +var_dump($props[0]->isProtected()); + +echo "=== 4th test ===\n"; + +class test5 { + private $value = 1; +} + +class test4 extends test5{ +} + +$Obj = new test4; +$Obj->value = 'value'; +$RefObj = new ReflectionObject($Obj); + +$props = $RefObj->getProperties(); + +var_dump($props); +var_dump($props[0]->isStatic()); +var_dump($props[0]->isPrivate()); +var_dump($props[0]->isPublic()); +var_dump($props[0]->isProtected()); + +echo "Done\n"; +?> +--EXPECTF-- +=== 1st test === + +Strict Standards: Creating default object from empty value in %s on line %d +array(1) { + [0]=> + &object(ReflectionProperty)#%d (2) { + ["name"]=> + string(5) "value" + ["class"]=> + string(8) "stdClass" + } +} +bool(false) +bool(false) +bool(true) +bool(false) +=== 2nd test === +array(1) { + [0]=> + &object(ReflectionProperty)#%d (2) { + ["name"]=> + string(5) "value" + ["class"]=> + string(5) "test2" + } +} +bool(false) +bool(false) +bool(true) +bool(false) +=== 3rd test === +array(1) { + [0]=> + &object(ReflectionProperty)#%d (2) { + ["name"]=> + string(5) "value" + ["class"]=> + string(5) "test3" + } +} +bool(false) +bool(false) +bool(true) +bool(false) +=== 4th test === +array(1) { + [0]=> + &object(ReflectionProperty)#%d (2) { + ["name"]=> + string(5) "value" + ["class"]=> + string(5) "test4" + } +} +bool(false) +bool(false) +bool(true) +bool(false) +Done +--UEXPECTF-- +=== 1st test === + +Strict Standards: Creating default object from empty value in %s on line %d +array(1) { + [0]=> + &object(ReflectionProperty)#%d (2) { + [u"name"]=> + unicode(5) "value" + [u"class"]=> + unicode(8) "stdClass" + } +} +bool(false) +bool(false) +bool(true) +bool(false) +=== 2nd test === +array(1) { + [0]=> + &object(ReflectionProperty)#%d (2) { + [u"name"]=> + unicode(5) "value" + [u"class"]=> + unicode(5) "test2" + } +} +bool(false) +bool(false) +bool(true) +bool(false) +=== 3rd test === +array(1) { + [0]=> + &object(ReflectionProperty)#%d (2) { + [u"name"]=> + unicode(5) "value" + [u"class"]=> + unicode(5) "test3" + } +} +bool(false) +bool(false) +bool(true) +bool(false) +=== 4th test === +array(1) { + [0]=> + &object(ReflectionProperty)#%d (2) { + [u"name"]=> + unicode(5) "value" + [u"class"]=> + unicode(5) "test4" + } +} +bool(false) +bool(false) +bool(true) +bool(false) +Done -- 2.40.0