Skip to content

Heap use-after-free in zend_assign_to_typed_property_reference #21897

@kdsjZh

Description

@kdsjZh

Description

The following code:

<?php
class Target { public string $s = "init"; }
class Evil {
    public function __toString(): string {
        global $target;
        $target = null;
        for ($i = 0; $i < 400; $i++) $GLOBALS['spray'][] = str_repeat("B", 96);
        return "x";
    }
}
$target = new Target();
$src = new Evil();
$target->s = &$src;  // typed-ref assign → zend_verify_prop_assignable_by_ref → __toString

Resulted in this output (w/USE_ZEND_ALLOC=0):

=================================================================
==960837==ERROR: AddressSanitizer: heap-use-after-free on address 0x50600001cd90 at pc 0x5b54bec4fa36 bp 0x7ffc2a22b7b0 sp 0x7ffc2a22b7a0
READ of size 1 at 0x50600001cd90 thread T0
    #0 0x5b54bec4fa35 in zval_get_type /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/Zend/zend_types.h:670
    #1 0x5b54bec58467 in zend_assign_to_typed_property_reference /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/Zend/zend_execute.c:588
    #2 0x5b54bec6df67 in zend_assign_to_property_reference /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/Zend/zend_execute.c:3671
    #3 0x5b54bec6e2cd in zend_assign_to_property_reference_var_const /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/Zend/zend_execute.c:3699
    #4 0x5b54beda8725 in ZEND_ASSIGN_OBJ_REF_SPEC_CV_CONST_OP_DATA_CV_HANDLER /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/Zend/zend_vm_execute.h:45786
    #5 0x5b54bedfb885 in execute_ex /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/Zend/zend_vm_execute.h:120990
    #6 0x5b54bedfefc0 in zend_execute /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/Zend/zend_vm_execute.h:121902
    #7 0x5b54bef631b0 in zend_execute_script /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/Zend/zend.c:1977
    #8 0x5b54be998623 in php_execute_script_ex /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/main/main.c:2641
    #9 0x5b54be998a33 in php_execute_script /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/main/main.c:2681
    #10 0x5b54bef68d20 in do_cli /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/sapi/cli/php_cli.c:951
    #11 0x5b54bef6b2ed in main /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/sapi/cli/php_cli.c:1362
    #12 0x7c77ee42a1c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #13 0x7c77ee42a28a in __libc_start_main_impl ../csu/libc-start.c:360
    #14 0x5b54bde03c94 in _start (/home/kdsj/workspace/project-crosslang/benchmark/php/build/PHP-8.5.5-asan/bin/php+0x403c94) (BuildId: 52663b68a3e6db4099478b4e11034e806ae2e302)

0x50600001cd90 is located 48 bytes inside of 56-byte region [0x50600001cd60,0x50600001cd98)
freed by thread T0 here:
    #0 0x7c77ee8fc4d8 in free ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:52
    #1 0x5b54beb4a0c3 in __zend_free /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/Zend/zend_alloc.c:3571
    #2 0x5b54beb45f30 in _efree /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/Zend/zend_alloc.c:2790
    #3 0x5b54beef7334 in zend_objects_store_del /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/Zend/zend_objects_API.c:200
    #4 0x5b54bef47ddf in rc_dtor_func /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/Zend/zend_variables.c:57
    #5 0x5b54bec53c5e in zend_assign_to_variable /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/Zend/zend_execute.h:183
    #6 0x5b54beda7f76 in ZEND_ASSIGN_SPEC_CV_CONST_RETVAL_UNUSED_HANDLER /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/Zend/zend_vm_execute.h:45688
    #7 0x5b54bedfb79b in execute_ex /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/Zend/zend_vm_execute.h:120975
    #8 0x5b54bec4a60e in zend_call_function /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/Zend/zend_execute_API.c:1010
    #9 0x5b54bec4b62f in zend_call_known_function /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/Zend/zend_execute_API.c:1104
    #10 0x5b54beee216e in zend_call_known_instance_method /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/Zend/zend_API.h:866
    #11 0x5b54beee21a8 in zend_call_known_instance_method_with_0_params /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/Zend/zend_API.h:872
    #12 0x5b54beef521d in zend_std_cast_object_tostring /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/Zend/zend_object_handlers.c:2499
    #13 0x5b54beb53b1f in zend_parse_arg_str_weak /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/Zend/zend_API.c:769
    #14 0x5b54bec59c27 in zend_verify_weak_scalar_type_hint /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/Zend/zend_execute.c:769
    #15 0x5b54bec5a135 in zend_verify_scalar_type_hint /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/Zend/zend_execute.c:836
    #16 0x5b54bec5bb3d in i_zend_check_property_type /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/Zend/zend_execute.c:1054
    #17 0x5b54bec71722 in zend_verify_prop_assignable_by_ref_ex /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/Zend/zend_execute.c:4106
    #18 0x5b54bec71848 in zend_verify_prop_assignable_by_ref /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/Zend/zend_execute.c:4122
    #19 0x5b54bec58448 in zend_assign_to_typed_property_reference /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/Zend/zend_execute.c:585
    #20 0x5b54bec6df67 in zend_assign_to_property_reference /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/Zend/zend_execute.c:3671
    #21 0x5b54bec6e2cd in zend_assign_to_property_reference_var_const /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/Zend/zend_execute.c:3699
    #22 0x5b54beda8725 in ZEND_ASSIGN_OBJ_REF_SPEC_CV_CONST_OP_DATA_CV_HANDLER /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/Zend/zend_vm_execute.h:45786
    #23 0x5b54bedfb885 in execute_ex /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/Zend/zend_vm_execute.h:120990
    #24 0x5b54bedfefc0 in zend_execute /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/Zend/zend_vm_execute.h:121902
    #25 0x5b54bef631b0 in zend_execute_script /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/Zend/zend.c:1977
    #26 0x5b54be998623 in php_execute_script_ex /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/main/main.c:2641
    #27 0x5b54be998a33 in php_execute_script /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/main/main.c:2681
    #28 0x5b54bef68d20 in do_cli /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/sapi/cli/php_cli.c:951
    #29 0x5b54bef6b2ed in main /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/sapi/cli/php_cli.c:1362

previously allocated by thread T0 here:
    #0 0x7c77ee8fd9c7 in malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:69
    #1 0x5b54beb49f7b in __zend_malloc /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/Zend/zend_alloc.c:3543
    #2 0x5b54beb45e53 in _emalloc /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/Zend/zend_alloc.c:2780
    #3 0x5b54beef9b62 in zend_objects_new /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/Zend/zend_objects.c:191
    #4 0x5b54beb5d054 in _object_and_properties_init /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/Zend/zend_API.c:1847
    #5 0x5b54beb5d20e in object_init_ex /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/Zend/zend_API.c:1870
    #6 0x5b54becc91dc in ZEND_NEW_SPEC_CONST_UNUSED_HANDLER /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/Zend/zend_vm_execute.h:11284
    #7 0x5b54bedee9de in execute_ex /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/Zend/zend_vm_execute.h:117563
    #8 0x5b54bedfefc0 in zend_execute /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/Zend/zend_vm_execute.h:121902
    #9 0x5b54bef631b0 in zend_execute_script /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/Zend/zend.c:1977
    #10 0x5b54be998623 in php_execute_script_ex /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/main/main.c:2641
    #11 0x5b54be998a33 in php_execute_script /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/main/main.c:2681
    #12 0x5b54bef68d20 in do_cli /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/sapi/cli/php_cli.c:951
    #13 0x5b54bef6b2ed in main /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/sapi/cli/php_cli.c:1362
    #14 0x7c77ee42a1c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #15 0x7c77ee42a28a in __libc_start_main_impl ../csu/libc-start.c:360
    #16 0x5b54bde03c94 in _start (/home/kdsj/workspace/project-crosslang/benchmark/php/build/PHP-8.5.5-asan/bin/php+0x403c94) (BuildId: 52663b68a3e6db4099478b4e11034e806ae2e302)

SUMMARY: AddressSanitizer: heap-use-after-free /home/kdsj/workspace/project-crosslang/benchmark/php/src/PHP-8.5.5-asan/Zend/zend_types.h:670 in zval_get_type
Shadow bytes around the buggy address:
  0x50600001cb00: fa fa fa fa 00 00 00 00 00 00 00 fa fa fa fa fa
  0x50600001cb80: 00 00 00 00 00 00 00 fa fa fa fa fa 00 00 00 00
  0x50600001cc00: 00 00 00 fa fa fa fa fa 00 00 00 00 00 00 00 fa
  0x50600001cc80: fa fa fa fa fd fd fd fd fd fd fd fa fa fa fa fa
  0x50600001cd00: fd fd fd fd fd fd fd fd fa fa fa fa fd fd fd fd
=>0x50600001cd80: fd fd[fd]fa fa fa fa fa 00 00 00 00 00 00 00 fa
  0x50600001ce00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x50600001ce80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x50600001cf00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x50600001cf80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x50600001d000: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==960837==ABORTING

But I expected this output instead:

PHP Version

PHP 8.5.5-dev (cli) (built: Apr 14 2026 18:43:12) (NTS DEBUG)
Copyright (c) The PHP Group
Zend Engine v4.5.5-dev, Copyright (c) Zend Technologies
    with Zend OPcache v8.5.5-dev, Copyright (c), by Zend Technologies

Operating System

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions