[php-src] Issue #24729: Use-after-free in ReflectionClass::setStaticPropertyValue() when the old value's destructor unbinds the property

From: Date: Mon, 26 Oct 2026 08:48:01 +0000
Subject: [php-src] Issue #24729: Use-after-free in ReflectionClass::setStaticPropertyValue() when the old value's destructor unbinds the property
Groups: php.bugs 
Request: Send a blank email to php-bugs+get-253207@lists.php.net to get a copy of this message
Issue: https://github.com/php/php-src/issues/24729 Author: IzaiahSun ### Description The following code: ```php <?php class A { public static $x; } class Old { public function __destruct() { unset($GLOBALS['y']); $z = 1; A::$x = &$z; } } $y = new Old; A::$x = &$y; (new ReflectionClass('A'))->setStaticPropertyValue('x', str_repeat('A', 64)); ``` Resulted in this output: ``` ==72025==ERROR: AddressSanitizer: heap-use-after-free on address 0x6040000291d0 at pc 0x0001011972f4 bp 0x00016fc83d20 sp 0x00016fc83d18 READ of size 4 at 0x6040000291d0 thread T0 #0 zend_gc_delref zend_types.h:1370 #1 zend_objects_store_del zend_objects_API.c:182 #2 rc_dtor_func zend_variables.c:57 #3 i_zval_ptr_dtor zend_variables.h:45 #4 zval_ptr_dtor zend_variables.c:84 #5 zim_ReflectionClass_setStaticPropertyValue php_reflection.c:4455 #6 ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER zend_vm_execute.h:1907 #7 execute_ex zend_vm_execute.h:58729 #8 zend_execute zend_vm_execute.h:64381 #9 zend_execute_script zend.c:1943 #10 php_execute_script_ex main.c:2623 freed by thread T0 here: #0 free(libclang_rt.asan_osx_dynamic.dylib:arm64e) #1 __zend_free zend_alloc.c:3728 #2 _efree zend_alloc.c:2889 #3 zend_objects_store_del zend_objects_API.c:200 #4 zend_object_release zend_objects_API.h:77 #5 zend_objects_destroy_object zend_objects.c:209 #6 zend_objects_store_del zend_objects_API.c:181 #7 rc_dtor_func zend_variables.c:57 #8 i_zval_ptr_dtor zend_variables.h:45 #9 zval_ptr_dtor zend_variables.c:84 #10 zim_ReflectionClass_setStaticPropertyValue php_reflection.c:4455 SUMMARY: AddressSanitizer: heap-use-after-free zend_types.h:1370 in zend_gc_delref ``` But I expected this output instead: ``` (no output, clean exit) ``` --- Debug + ASan build, run with USE_ZEND_ALLOC=0. ReflectionClass::setStaticPropertyValue() destroys the old value of the static property before storing the new one, while variable_ptr still points into the reference it is about to write. If the old value's destructor drops the last holder of that reference, the write lands in freed memory. ext/reflection/php_reflection.c: ```c zval_ptr_dtor(variable_ptr); ZVAL_COPY(variable_ptr, value); ``` ### PHP Version ```plain PHP 8.4.28-dev (cli) (built: Oct 25 2026 01:02:13) (NTS DEBUG) Copyright (c) The PHP Group Zend Engine v4.4.28-dev, Copyright (c) Zend Technologies Also reproduced on master (29b5e168bf): PHP 8.7.0-dev (cli) (built: Oct 24 2026 21:13:17) (NTS DEBUG) Copyright © The PHP Group and Contributors Zend Engine v4.7.0-dev, Copyright © Zend by Perforce with Zend OPcache v8.7.0-dev, Copyright ©, by Zend by Perforce ``` ### Operating System macOS 27.0.1 (arm64)

« previous php.bugs (#253207) next »