mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
Fix use-after-free in write_property when object is released
Fixes GH-10169 Closes GH-10179
This commit is contained in:
37
Zend/tests/gh10169.phpt
Normal file
37
Zend/tests/gh10169.phpt
Normal file
@@ -0,0 +1,37 @@
|
||||
--TEST--
|
||||
GH-10169: Fix use-after-free when releasing object during property assignment
|
||||
--FILE--
|
||||
<?php
|
||||
class A
|
||||
{
|
||||
public string $prop;
|
||||
}
|
||||
class B
|
||||
{
|
||||
public function __toString()
|
||||
{
|
||||
global $a;
|
||||
$a = null;
|
||||
return str_repeat('a', 1);
|
||||
}
|
||||
}
|
||||
|
||||
$a = new A();
|
||||
try {
|
||||
$a->prop = new B();
|
||||
} catch (Error $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
$a = new A();
|
||||
$a->prop = '';
|
||||
try {
|
||||
$a->prop = new B();
|
||||
} catch (Error $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Object was released while assigning to property A::$prop
|
||||
Object was released while assigning to property A::$prop
|
||||
@@ -899,6 +899,12 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_invalid_class_constant_type_error(zen
|
||||
zend_type_error("Cannot use value of type %s as class constant name", zend_get_type_by_const(type));
|
||||
}
|
||||
|
||||
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_object_released_while_assigning_to_property_error(const zend_property_info *info)
|
||||
{
|
||||
zend_throw_error(NULL, "Object was released while assigning to property %s::$%s",
|
||||
ZSTR_VAL(info->ce->name), zend_get_unmangled_property_name(info->name));
|
||||
}
|
||||
|
||||
static const zend_class_entry *resolve_single_class_type(zend_string *name, const zend_class_entry *self_ce) {
|
||||
if (zend_string_equals_literal_ci(name, "self")) {
|
||||
return self_ce;
|
||||
|
||||
@@ -84,6 +84,8 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_readonly_property_indirect_modificati
|
||||
|
||||
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_invalid_class_constant_type_error(zend_uchar type);
|
||||
|
||||
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_object_released_while_assigning_to_property_error(const zend_property_info *info);
|
||||
|
||||
ZEND_API bool zend_verify_scalar_type_hint(uint32_t type_mask, zval *arg, bool strict, bool is_internal_arg);
|
||||
ZEND_API ZEND_COLD void zend_verify_arg_error(
|
||||
const zend_function *zf, const zend_arg_info *arg_info, uint32_t arg_num, zval *value);
|
||||
|
||||
@@ -818,7 +818,17 @@ ZEND_API zval *zend_std_write_property(zend_object *zobj, zend_string *name, zva
|
||||
}
|
||||
|
||||
ZVAL_COPY_VALUE(&tmp, value);
|
||||
if (UNEXPECTED(!zend_verify_property_type(prop_info, &tmp, property_uses_strict_types()))) {
|
||||
// Increase refcount to prevent object from being released in __toString()
|
||||
GC_ADDREF(zobj);
|
||||
bool type_matched = zend_verify_property_type(prop_info, &tmp, property_uses_strict_types());
|
||||
if (UNEXPECTED(GC_DELREF(zobj) == 0)) {
|
||||
zend_object_released_while_assigning_to_property_error(prop_info);
|
||||
zend_objects_store_del(zobj);
|
||||
zval_ptr_dtor(&tmp);
|
||||
variable_ptr = &EG(error_zval);
|
||||
goto exit;
|
||||
}
|
||||
if (UNEXPECTED(!type_matched)) {
|
||||
Z_TRY_DELREF_P(value);
|
||||
variable_ptr = &EG(error_zval);
|
||||
goto exit;
|
||||
@@ -889,7 +899,17 @@ write_std_property:
|
||||
}
|
||||
|
||||
ZVAL_COPY_VALUE(&tmp, value);
|
||||
if (UNEXPECTED(!zend_verify_property_type(prop_info, &tmp, property_uses_strict_types()))) {
|
||||
// Increase refcount to prevent object from being released in __toString()
|
||||
GC_ADDREF(zobj);
|
||||
bool type_matched = zend_verify_property_type(prop_info, &tmp, property_uses_strict_types());
|
||||
if (UNEXPECTED(GC_DELREF(zobj) == 0)) {
|
||||
zend_object_released_while_assigning_to_property_error(prop_info);
|
||||
zend_objects_store_del(zobj);
|
||||
zval_ptr_dtor(&tmp);
|
||||
variable_ptr = &EG(error_zval);
|
||||
goto exit;
|
||||
}
|
||||
if (UNEXPECTED(!type_matched)) {
|
||||
zval_ptr_dtor(value);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user