mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
Merge branch 'PHP-8.4' into PHP-8.5
* PHP-8.4: Fix GH-20875: Propagate IN_GET guard in get_property_ptr_ptr for lazy proxies
This commit is contained in:
2
NEWS
2
NEWS
@@ -5,6 +5,8 @@ PHP NEWS
|
|||||||
- Core:
|
- Core:
|
||||||
. Fixed bug GH-20672 (Incorrect property_info sizing for locally shadowed
|
. Fixed bug GH-20672 (Incorrect property_info sizing for locally shadowed
|
||||||
trait properties). (ilutov)
|
trait properties). (ilutov)
|
||||||
|
. Fixed bugs GH-20875, GH-20873, GH-20854 (Propagate IN_GET guard in
|
||||||
|
get_property_ptr_ptr for lazy proxies). (iliaal)
|
||||||
|
|
||||||
- Bz2:
|
- Bz2:
|
||||||
. Fix truncation of total output size causing erroneous errors. (ndossche)
|
. Fix truncation of total output size causing erroneous errors. (ndossche)
|
||||||
|
|||||||
22
Zend/tests/lazy_objects/gh20854.phpt
Normal file
22
Zend/tests/lazy_objects/gh20854.phpt
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
--TEST--
|
||||||
|
GH-20854 (Assertion in ZEND_RETURN_BY_REF with lazy proxy and return-by-ref __get)
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
class C {
|
||||||
|
public $prop;
|
||||||
|
|
||||||
|
function &__get($name) {
|
||||||
|
return $this->x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$rc = new ReflectionClass(C::class);
|
||||||
|
$obj = $rc->newLazyProxy(function () {
|
||||||
|
return new C;
|
||||||
|
});
|
||||||
|
$obj->x;
|
||||||
|
echo "Done\n";
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Deprecated: Creation of dynamic property C::$x is deprecated in %s on line %d
|
||||||
|
Done
|
||||||
30
Zend/tests/lazy_objects/gh20873.phpt
Normal file
30
Zend/tests/lazy_objects/gh20873.phpt
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
--TEST--
|
||||||
|
GH-20873 (Assertion failure in _zendi_try_convert_scalar_to_number with lazy proxy)
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
class A {
|
||||||
|
public $_;
|
||||||
|
public function __get($n) {
|
||||||
|
global $obj;
|
||||||
|
$obj->x =& $this->_;
|
||||||
|
static $a = $a;
|
||||||
|
$e =& $this->_ - $a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$rc = new ReflectionClass(A::class);
|
||||||
|
$obj = $rc->newLazyProxy(fn() => new A);
|
||||||
|
$rc->initializeLazyObject($obj);
|
||||||
|
var_dump($obj->p);
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Deprecated: Creation of dynamic property A::$x is deprecated in %s on line %d
|
||||||
|
|
||||||
|
Warning: Undefined variable $a in %s on line %d
|
||||||
|
|
||||||
|
Notice: Indirect modification of overloaded property A::$x has no effect in %s on line %d
|
||||||
|
|
||||||
|
Fatal error: Uncaught Error: Cannot assign by reference to overloaded object in %s:%d
|
||||||
|
Stack trace:
|
||||||
|
#0 %s(%d): A->__get('p')
|
||||||
|
#1 {main}
|
||||||
|
thrown in %s on line %d
|
||||||
49
Zend/tests/lazy_objects/gh20875.phpt
Normal file
49
Zend/tests/lazy_objects/gh20875.phpt
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
--TEST--
|
||||||
|
GH-20875 (Assertion failure in _get_zval_ptr_tmp with lazy proxy)
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
class A {
|
||||||
|
public $_;
|
||||||
|
public function __get($name) {
|
||||||
|
global $obj;
|
||||||
|
$obj->f =& $this->b - $x > $y = new StdClass;
|
||||||
|
static $a = $a;
|
||||||
|
$t = 'x';
|
||||||
|
foreach (get_defined_vars() as $key => $e) {}
|
||||||
|
if ($v ==!1) $x = $a ?: $t = "ok";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$rc = new ReflectionClass(A::class);
|
||||||
|
$obj = $rc->newLazyProxy(function () { return new A; });
|
||||||
|
$real = $rc->initializeLazyObject($obj);
|
||||||
|
var_dump($real->prop);
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Deprecated: Creation of dynamic property A::$b is deprecated in %s on line %d
|
||||||
|
|
||||||
|
Deprecated: Creation of dynamic property A::$f is deprecated in %s on line %d
|
||||||
|
|
||||||
|
Warning: Undefined variable $x in %s on line %d
|
||||||
|
|
||||||
|
Notice: Object of class stdClass could not be converted to int in %s on line %d
|
||||||
|
|
||||||
|
Warning: Undefined variable $a in %s on line %d
|
||||||
|
|
||||||
|
Warning: Undefined variable $v in %s on line %d
|
||||||
|
|
||||||
|
Notice: Indirect modification of overloaded property A::$b has no effect in %s on line %d
|
||||||
|
|
||||||
|
Warning: Undefined variable $x in %s on line %d
|
||||||
|
|
||||||
|
Notice: Object of class stdClass could not be converted to int in %s on line %d
|
||||||
|
|
||||||
|
Warning: Undefined variable $v in %s on line %d
|
||||||
|
|
||||||
|
Notice: Indirect modification of overloaded property A::$f has no effect in %s on line %d
|
||||||
|
|
||||||
|
Fatal error: Uncaught Error: Cannot assign by reference to overloaded object in %s:%d
|
||||||
|
Stack trace:
|
||||||
|
#0 %s(%d): A->__get('b')
|
||||||
|
#1 %s(%d): A->__get('prop')
|
||||||
|
#2 {main}
|
||||||
|
thrown in %s on line %d
|
||||||
23
Zend/tests/lazy_objects/gh20875_proxy_get_no_init.phpt
Normal file
23
Zend/tests/lazy_objects/gh20875_proxy_get_no_init.phpt
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
--TEST--
|
||||||
|
GH-20875 (Lazy proxy should not initialize when __get handles dynamic property access)
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class Foo {
|
||||||
|
public $_;
|
||||||
|
|
||||||
|
public function &__get($name) {
|
||||||
|
echo "__get\n";
|
||||||
|
return $name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$proxy = (new ReflectionClass(Foo::class))->newLazyProxy(function () {
|
||||||
|
echo "init\n";
|
||||||
|
return new Foo();
|
||||||
|
});
|
||||||
|
$x = &$proxy->x;
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
__get
|
||||||
@@ -1405,12 +1405,24 @@ try_again:
|
|||||||
UNEXPECTED((*zend_get_property_guard(zobj, name)) & IN_GET) ||
|
UNEXPECTED((*zend_get_property_guard(zobj, name)) & IN_GET) ||
|
||||||
UNEXPECTED(prop_info && (Z_PROP_FLAG_P(retval) & IS_PROP_UNINIT))) {
|
UNEXPECTED(prop_info && (Z_PROP_FLAG_P(retval) & IS_PROP_UNINIT))) {
|
||||||
if (UNEXPECTED(zend_lazy_object_must_init(zobj) && (Z_PROP_FLAG_P(retval) & IS_PROP_LAZY))) {
|
if (UNEXPECTED(zend_lazy_object_must_init(zobj) && (Z_PROP_FLAG_P(retval) & IS_PROP_LAZY))) {
|
||||||
zobj = zend_lazy_object_init(zobj);
|
bool guarded = zobj->ce->__get
|
||||||
if (!zobj) {
|
&& (*zend_get_property_guard(zobj, name) & IN_GET);
|
||||||
|
zend_object *instance = zend_lazy_object_init(zobj);
|
||||||
|
if (!instance) {
|
||||||
return &EG(error_zval);
|
return &EG(error_zval);
|
||||||
}
|
}
|
||||||
|
|
||||||
return zend_std_get_property_ptr_ptr(zobj, name, type, cache_slot);
|
if (guarded && (instance->ce->ce_flags & ZEND_ACC_USE_GUARDS)) {
|
||||||
|
uint32_t *guard = zend_get_property_guard(instance, name);
|
||||||
|
if (!(*guard & IN_GET)) {
|
||||||
|
(*guard) |= IN_GET;
|
||||||
|
retval = zend_std_get_property_ptr_ptr(instance, name, type, cache_slot);
|
||||||
|
(*guard) &= ~IN_GET;
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return zend_std_get_property_ptr_ptr(instance, name, type, cache_slot);
|
||||||
}
|
}
|
||||||
if (UNEXPECTED(type == BP_VAR_RW || type == BP_VAR_R)) {
|
if (UNEXPECTED(type == BP_VAR_RW || type == BP_VAR_R)) {
|
||||||
if (prop_info) {
|
if (prop_info) {
|
||||||
@@ -1453,6 +1465,25 @@ try_again:
|
|||||||
}
|
}
|
||||||
if (EXPECTED(!zobj->ce->__get) ||
|
if (EXPECTED(!zobj->ce->__get) ||
|
||||||
UNEXPECTED((*zend_get_property_guard(zobj, name)) & IN_GET)) {
|
UNEXPECTED((*zend_get_property_guard(zobj, name)) & IN_GET)) {
|
||||||
|
if (UNEXPECTED(zend_lazy_object_must_init(zobj))) {
|
||||||
|
bool guarded = (zobj->ce->__get != NULL);
|
||||||
|
zend_object *instance = zend_lazy_object_init(zobj);
|
||||||
|
if (!instance) {
|
||||||
|
return &EG(error_zval);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (guarded && (instance->ce->ce_flags & ZEND_ACC_USE_GUARDS)) {
|
||||||
|
uint32_t *guard = zend_get_property_guard(instance, name);
|
||||||
|
if (!(*guard & IN_GET)) {
|
||||||
|
(*guard) |= IN_GET;
|
||||||
|
retval = zend_std_get_property_ptr_ptr(instance, name, type, cache_slot);
|
||||||
|
(*guard) &= ~IN_GET;
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return zend_std_get_property_ptr_ptr(instance, name, type, cache_slot);
|
||||||
|
}
|
||||||
if (UNEXPECTED(zobj->ce->ce_flags & ZEND_ACC_NO_DYNAMIC_PROPERTIES)) {
|
if (UNEXPECTED(zobj->ce->ce_flags & ZEND_ACC_NO_DYNAMIC_PROPERTIES)) {
|
||||||
zend_forbidden_dynamic_property(zobj->ce, name);
|
zend_forbidden_dynamic_property(zobj->ce, name);
|
||||||
return &EG(error_zval);
|
return &EG(error_zval);
|
||||||
@@ -1462,14 +1493,6 @@ try_again:
|
|||||||
return &EG(error_zval);
|
return &EG(error_zval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (UNEXPECTED(zend_lazy_object_must_init(zobj))) {
|
|
||||||
zobj = zend_lazy_object_init(zobj);
|
|
||||||
if (!zobj) {
|
|
||||||
return &EG(error_zval);
|
|
||||||
}
|
|
||||||
|
|
||||||
return zend_std_get_property_ptr_ptr(zobj, name, type, cache_slot);
|
|
||||||
}
|
|
||||||
if (UNEXPECTED(!zobj->properties)) {
|
if (UNEXPECTED(!zobj->properties)) {
|
||||||
rebuild_object_properties_internal(zobj);
|
rebuild_object_properties_internal(zobj);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user