mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
Fixed bug #72177 (Scope issue in __destruct after ReflectionProperty::setValue())
This commit is contained in:
parent
ee8f402af8
commit
e9c3f9fcde
4 changed files with 96 additions and 0 deletions
35
Zend/tests/bug72177.phpt
Normal file
35
Zend/tests/bug72177.phpt
Normal file
|
@ -0,0 +1,35 @@
|
|||
--TEST--
|
||||
Bug #72177 Scope issue in __destruct after ReflectionProperty::setValue()
|
||||
--FILE--
|
||||
<?php
|
||||
class Child
|
||||
{
|
||||
protected $bar;
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
$this->bar = null;
|
||||
}
|
||||
}
|
||||
|
||||
class Parnt
|
||||
{
|
||||
protected $child;
|
||||
|
||||
public function doSomething()
|
||||
{
|
||||
$this->child = new Child();
|
||||
|
||||
$prop = new \ReflectionProperty($this, 'child');
|
||||
$prop->setAccessible(true);
|
||||
$prop->setValue($this, null);
|
||||
}
|
||||
}
|
||||
|
||||
$p = new Parnt();
|
||||
$p->doSomething();
|
||||
|
||||
echo "OK\n";
|
||||
?>
|
||||
--EXPECT--
|
||||
OK
|
34
Zend/tests/bug72177_2.phpt
Normal file
34
Zend/tests/bug72177_2.phpt
Normal file
|
@ -0,0 +1,34 @@
|
|||
--TEST--
|
||||
Bug #72177 Scope issue in __destruct after ReflectionProperty::setValue()
|
||||
--FILE--
|
||||
<?php
|
||||
class Foo
|
||||
{
|
||||
private $bar = 'bar';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
unset($this->bar);
|
||||
}
|
||||
}
|
||||
|
||||
class Bar extends Foo
|
||||
{
|
||||
private $baz = 'baz';
|
||||
private static $tab = 'tab';
|
||||
|
||||
public function __get(string $name)
|
||||
{
|
||||
var_dump($this->baz);
|
||||
var_dump(self::$tab);
|
||||
return $name;
|
||||
}
|
||||
}
|
||||
|
||||
$r = new ReflectionProperty(Foo::class, 'bar');
|
||||
|
||||
$r->setAccessible(true);
|
||||
echo "OK\n";
|
||||
?>
|
||||
--EXPECT--
|
||||
OK
|
|
@ -191,6 +191,9 @@ ZEND_API HashTable *zend_std_get_debug_info(zval *object, int *is_temp) /* {{{ *
|
|||
static void zend_std_call_getter(zval *object, zval *member, zval *retval) /* {{{ */
|
||||
{
|
||||
zend_class_entry *ce = Z_OBJCE_P(object);
|
||||
zend_class_entry *orig_fake_scope = EG(fake_scope);
|
||||
|
||||
EG(fake_scope) = NULL;
|
||||
|
||||
/* __get handler is called with one argument:
|
||||
property name
|
||||
|
@ -202,6 +205,8 @@ static void zend_std_call_getter(zval *object, zval *member, zval *retval) /* {{
|
|||
zend_call_method_with_1_params(object, ce, &ce->__get, ZEND_GET_FUNC_NAME, retval, member);
|
||||
|
||||
zval_ptr_dtor(member);
|
||||
|
||||
EG(fake_scope) = orig_fake_scope;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
@ -210,6 +215,9 @@ static int zend_std_call_setter(zval *object, zval *member, zval *value) /* {{{
|
|||
zval retval;
|
||||
int result;
|
||||
zend_class_entry *ce = Z_OBJCE_P(object);
|
||||
zend_class_entry *orig_fake_scope = EG(fake_scope);
|
||||
|
||||
EG(fake_scope) = NULL;
|
||||
|
||||
if (Z_REFCOUNTED_P(member)) Z_ADDREF_P(member);
|
||||
if (Z_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
||||
|
@ -228,8 +236,10 @@ static int zend_std_call_setter(zval *object, zval *member, zval *value) /* {{{
|
|||
if (Z_TYPE(retval) != IS_UNDEF) {
|
||||
result = i_zend_is_true(&retval) ? SUCCESS : FAILURE;
|
||||
zval_ptr_dtor(&retval);
|
||||
EG(fake_scope) = orig_fake_scope;
|
||||
return result;
|
||||
} else {
|
||||
EG(fake_scope) = orig_fake_scope;
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
|
@ -238,6 +248,9 @@ static int zend_std_call_setter(zval *object, zval *member, zval *value) /* {{{
|
|||
static void zend_std_call_unsetter(zval *object, zval *member) /* {{{ */
|
||||
{
|
||||
zend_class_entry *ce = Z_OBJCE_P(object);
|
||||
zend_class_entry *orig_fake_scope = EG(fake_scope);
|
||||
|
||||
EG(fake_scope) = NULL;
|
||||
|
||||
/* __unset handler is called with one argument:
|
||||
property name
|
||||
|
@ -248,12 +261,17 @@ static void zend_std_call_unsetter(zval *object, zval *member) /* {{{ */
|
|||
zend_call_method_with_1_params(object, ce, &ce->__unset, ZEND_UNSET_FUNC_NAME, NULL, member);
|
||||
|
||||
zval_ptr_dtor(member);
|
||||
|
||||
EG(fake_scope) = orig_fake_scope;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void zend_std_call_issetter(zval *object, zval *member, zval *retval) /* {{{ */
|
||||
{
|
||||
zend_class_entry *ce = Z_OBJCE_P(object);
|
||||
zend_class_entry *orig_fake_scope = EG(fake_scope);
|
||||
|
||||
EG(fake_scope) = NULL;
|
||||
|
||||
/* __isset handler is called with one argument:
|
||||
property name
|
||||
|
@ -266,6 +284,8 @@ static void zend_std_call_issetter(zval *object, zval *member, zval *retval) /*
|
|||
zend_call_method_with_1_params(object, ce, &ce->__isset, ZEND_ISSET_FUNC_NAME, retval, member);
|
||||
|
||||
zval_ptr_dtor(member);
|
||||
|
||||
EG(fake_scope) = orig_fake_scope;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
|
|
@ -91,7 +91,9 @@ ZEND_API void zend_objects_destroy_object(zend_object *object)
|
|||
if (destructor) {
|
||||
zend_object *old_exception;
|
||||
zval obj;
|
||||
zend_class_entry *orig_fake_scope = NULL;
|
||||
|
||||
EG(fake_scope) = NULL;
|
||||
if (destructor->op_array.fn_flags & (ZEND_ACC_PRIVATE|ZEND_ACC_PROTECTED)) {
|
||||
if (destructor->op_array.fn_flags & ZEND_ACC_PRIVATE) {
|
||||
/* Ensure that if we're calling a private function, we're allowed to do so.
|
||||
|
@ -104,12 +106,14 @@ ZEND_API void zend_objects_destroy_object(zend_object *object)
|
|||
"Call to private %s::__destruct() from context '%s'",
|
||||
ZSTR_VAL(object->ce->name),
|
||||
scope ? ZSTR_VAL(scope->name) : "");
|
||||
EG(fake_scope) = orig_fake_scope;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
zend_error(E_WARNING,
|
||||
"Call to private %s::__destruct() from context '' during shutdown ignored",
|
||||
ZSTR_VAL(object->ce->name));
|
||||
EG(fake_scope) = orig_fake_scope;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
|
@ -123,12 +127,14 @@ ZEND_API void zend_objects_destroy_object(zend_object *object)
|
|||
"Call to protected %s::__destruct() from context '%s'",
|
||||
ZSTR_VAL(object->ce->name),
|
||||
scope ? ZSTR_VAL(scope->name) : "");
|
||||
EG(fake_scope) = orig_fake_scope;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
zend_error(E_WARNING,
|
||||
"Call to protected %s::__destruct() from context '' during shutdown ignored",
|
||||
ZSTR_VAL(object->ce->name));
|
||||
EG(fake_scope) = orig_fake_scope;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -159,6 +165,7 @@ ZEND_API void zend_objects_destroy_object(zend_object *object)
|
|||
}
|
||||
}
|
||||
zval_ptr_dtor(&obj);
|
||||
EG(fake_scope) = orig_fake_scope;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue