diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index f5b1cb2010a0..00085968be79 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -4600,19 +4600,17 @@ ZEND_METHOD(ReflectionClass, hasProperty) } GET_REFLECTION_OBJECT_PTR(ce); - if ((property_info = zend_hash_find_ptr(&ce->properties_info, name)) != NULL) { - if ((property_info->flags & ZEND_ACC_PRIVATE) && property_info->ce != ce) { - RETURN_FALSE; - } + if ((property_info = zend_hash_find_ptr(&ce->properties_info, name)) != NULL + && (!(property_info->flags & ZEND_ACC_PRIVATE) + || property_info->ce == ce)) { RETURN_TRUE; - } else { - if (Z_TYPE(intern->obj) != IS_UNDEF) { - if (Z_OBJ_HANDLER(intern->obj, has_property)(Z_OBJ(intern->obj), name, ZEND_PROPERTY_EXISTS, NULL)) { - RETURN_TRUE; - } + } + if (Z_TYPE(intern->obj) != IS_UNDEF) { + if (Z_OBJ_HANDLER(intern->obj, has_property)(Z_OBJ(intern->obj), name, ZEND_PROPERTY_EXISTS, NULL)) { + RETURN_TRUE; } - RETURN_FALSE; } + RETURN_FALSE; } /* }}} */ @@ -4631,12 +4629,13 @@ ZEND_METHOD(ReflectionClass, getProperty) } GET_REFLECTION_OBJECT_PTR(ce); - if ((property_info = zend_hash_find_ptr(&ce->properties_info, name)) != NULL) { - if (!(property_info->flags & ZEND_ACC_PRIVATE) || property_info->ce == ce) { - reflection_property_factory(ce, name, property_info, return_value); - return; - } - } else if (Z_TYPE(intern->obj) != IS_UNDEF) { + if ((property_info = zend_hash_find_ptr(&ce->properties_info, name)) != NULL + && (!(property_info->flags & ZEND_ACC_PRIVATE) + || property_info->ce == ce)) { + reflection_property_factory(ce, name, property_info, return_value); + return; + } + if (Z_TYPE(intern->obj) != IS_UNDEF) { /* Check for dynamic properties */ if (zend_hash_exists(Z_OBJ_HT(intern->obj)->get_properties(Z_OBJ(intern->obj)), name)) { reflection_property_factory(ce, name, NULL, return_value); diff --git a/ext/reflection/tests/gh22441.phpt b/ext/reflection/tests/gh22441.phpt new file mode 100644 index 000000000000..9ca3cb0eee74 --- /dev/null +++ b/ext/reflection/tests/gh22441.phpt @@ -0,0 +1,44 @@ +--TEST-- +GH-22441 (ReflectionClass::hasProperty()/getProperty() ignore dynamic properties shadowing a private parent property) +--FILE-- +shadow = true; +$o->noShadow = true; + +$r = new ReflectionObject($o); + +echo "hasProperty:\n"; +echo "shadow (dynamic over private parent): "; var_dump($r->hasProperty('shadow')); +echo "noShadow (plain dynamic): "; var_dump($r->hasProperty('noShadow')); +echo "onlyBase (private parent, no dynamic): "; var_dump($r->hasProperty('onlyBase')); + +echo "\ngetProperty:\n"; +foreach (['shadow', 'noShadow', 'onlyBase'] as $name) { + try { + $p = $r->getProperty($name); + printf("%s: %s::\$%s\n", $name, $p->getDeclaringClass()->getName(), $p->getName()); + } catch (ReflectionException $e) { + printf("%s: %s\n", $name, $e->getMessage()); + } +} +?> +--EXPECT-- +hasProperty: +shadow (dynamic over private parent): bool(true) +noShadow (plain dynamic): bool(true) +onlyBase (private parent, no dynamic): bool(false) + +getProperty: +shadow: Child::$shadow +noShadow: Child::$noShadow +onlyBase: Property Child::$onlyBase does not exist diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c index f662bb8a1dbd..ccab32aec783 100644 --- a/ext/spl/spl_directory.c +++ b/ext/spl/spl_directory.c @@ -2150,6 +2150,8 @@ PHP_METHOD(SplFileObject, next) ZEND_PARSE_PARAMETERS_NONE(); + CHECK_SPL_FILE_OBJECT_IS_INITIALIZED(intern); + if (!intern->u.file.current_line && Z_ISUNDEF(intern->u.file.current_zval)) { if (spl_filesystem_file_read_line(ZEND_THIS, intern, true) == FAILURE) { return; @@ -2300,6 +2302,8 @@ PHP_METHOD(SplFileObject, fputcsv) RETURN_THROWS(); } + CHECK_SPL_FILE_OBJECT_IS_INITIALIZED(intern); + if (delim) { if (d_len != 1) { zend_argument_value_error(2, "must be a single character"); diff --git a/ext/spl/tests/gh16217.phpt b/ext/spl/tests/gh16217.phpt new file mode 100644 index 000000000000..71760389c8e4 --- /dev/null +++ b/ext/spl/tests/gh16217.phpt @@ -0,0 +1,35 @@ +--TEST-- +GH-16217 (SplFileObject methods on an uninitialized object segfault) +--FILE-- +newInstanceWithoutConstructor(); +} + +try { + (new ReflectionMethod(SplFileObject::class, "fputcsv"))->invoke(uninitialized(), []); +} catch (Error $e) { + echo "fputcsv: ", $e->getMessage(), "\n"; +} + +try { + (new ReflectionMethod(SplFileObject::class, "next"))->invoke(uninitialized()); +} catch (Error $e) { + echo "next: ", $e->getMessage(), "\n"; +} + +$obj = uninitialized(); +(new ReflectionMethod(SplFileObject::class, "setFlags"))->invoke($obj, SplFileObject::READ_AHEAD); +try { + (new ReflectionMethod(SplFileObject::class, "next"))->invoke($obj); +} catch (Error $e) { + echo "next (READ_AHEAD): ", $e->getMessage(), "\n"; +} + +echo "Done\n"; +?> +--EXPECT-- +fputcsv: Object not initialized +next: Object not initialized +next (READ_AHEAD): Object not initialized +Done