Skip to content

Heap use-after-free in array assignment (ZEND_ASSIGN_DIM) via re-entrant user output handler during __destruct() #20482

@vi3tL0u1s

Description

@vi3tL0u1s

Description

The following code:

<?php
class a {
    function __destruct() {
        $c = new A;
        $array = array($c);
        $c = get_declared_classes();
        ob_start(function () use (&$c) {
            $c =/////
            var_dump(parse_ini_string(<<<INI
            INI
            , TRUE, INI_SCANNER_TYPED));
	        return '';
        }, 1);
			$c[~~@~~-7] = //
    $xs;
    $x != $$i= $a ?: $c = 0;
    }
}
new a;

Command:

USE_ZEND_ALLOC=0 ./php-src-latest/sapi/cli/php poc.php

Resulted in this output:

Deprecated: a::__destruct(): Producing output from user output handler {closure:a::__destruct():7} is deprecated in /path/to/poc.php on line 14
=================================================================
==3156334==ERROR: AddressSanitizer: heap-use-after-free on address 0x62600000b429 at pc 0x55bdab9da2e4 bp 0x7fff5a9ca9e0 sp 0x7fff5a9ca9d8
READ of size 1 at 0x62600000b429 thread T0
    #0 0x55bdab9da2e3 in zend_assign_to_variable_ex /path/to/php-src/Zend/zend_execute.h:195:7
    #1 0x55bdab7f375b in ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DATA_CV_HANDLER /path/to/php-src/Zend/zend_vm_execute.h:45586:12
    #2 0x55bdab7a2492 in execute_ex /path/to/php-src/Zend/zend_vm_execute.h:116212:12
    #3 0x55bdab77cac1 in zend_call_function /path/to/php-src/Zend/zend_execute_API.c:1014:3
    #4 0x55bdab77ecd2 in zend_call_known_function /path/to/php-src/Zend/zend_execute_API.c:1108:23
    #5 0x55bdabb5205a in zend_call_known_instance_method /path/to/php-src/Zend/zend_API.h:862:2
    #6 0x55bdabb4f8bb in zend_call_known_instance_method_with_0_params /path/to/php-src/Zend/zend_API.h:868:2
    #7 0x55bdabb4f2b1 in zend_objects_destroy_object /path/to/php-src/Zend/zend_objects.c:172:3
    #8 0x55bdabb4ce12 in zend_objects_store_del /path/to/php-src/Zend/zend_objects_API.c:181:4
    #9 0x55bdabbb67d6 in rc_dtor_func /path/to/php-src/Zend/zend_variables.c:57:2
    #10 0x55bdab797a2c in zval_ptr_dtor_nogc /path/to/php-src/Zend/zend_variables.h:36:3
    #11 0x55bdab897800 in ZEND_FREE_SPEC_TMPVAR_HANDLER /path/to/php-src/Zend/zend_vm_execute.h:15675:2
    #12 0x55bdab7a2492 in execute_ex /path/to/php-src/Zend/zend_vm_execute.h:116212:12
    #13 0x55bdab7a2d97 in zend_execute /path/to/php-src/Zend/zend_vm_execute.h:121924:2
    #14 0x55bdabbd65d0 in zend_execute_script /path/to/php-src/Zend/zend.c:1975:3
    #15 0x55bdab3d788b in php_execute_script_ex /path/to/php-src/main/main.c:2645:13
    #16 0x55bdab3d7d88 in php_execute_script /path/to/php-src/main/main.c:2685:9
    #17 0x55bdabbde4d2 in do_cli /path/to/php-src/sapi/cli/php_cli.c:951:5
    #18 0x55bdabbdb42c in main /path/to/php-src/sapi/cli/php_cli.c:1362:18
    #19 0x7f14f3b7ad8f  (/lib/x86_64-linux-gnu/libc.so.6+0x29d8f) (BuildId: 4f7b0c955c3d81d7cac1501a2498b69d1d82bfe7)
    #20 0x7f14f3b7ae3f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e3f) (BuildId: 4f7b0c955c3d81d7cac1501a2498b69d1d82bfe7)
    #21 0x55bdaa003374 in _start (/path/to/php-src/sapi/cli/php+0x603374) (BuildId: 78daf5f832c7fdbb3fc64cdca7de50663e951019)

0x62600000b429 is located 9001 bytes inside of 10240-byte region [0x626000009100,0x62600000b900)
freed by thread T0 here:
    #0 0x55bdaa085f12 in free (/path/to/php-src/sapi/cli/php+0x685f12) (BuildId: 78daf5f832c7fdbb3fc64cdca7de50663e951019)
    #1 0x55bdab621a83 in __zend_free /path/to/php-src/Zend/zend_alloc.c:3571:2
    #2 0x55bdab625c44 in _efree /path/to/php-src/Zend/zend_alloc.c:2790:3
    #3 0x55bdaba46908 in zend_array_destroy /path/to/php-src/Zend/zend_hash.c:1876:2
    #4 0x55bdabbb67d6 in rc_dtor_func /path/to/php-src/Zend/zend_variables.c:57:2
    #5 0x55bdab9d9ec4 in zend_assign_to_variable /path/to/php-src/Zend/zend_execute.h:183:4
    #6 0x55bdab7d9c69 in ZEND_ASSIGN_SPEC_CV_VAR_RETVAL_UNUSED_HANDLER /path/to/php-src/Zend/zend_vm_execute.h:50823:11
    #7 0x55bdab7a2492 in execute_ex /path/to/php-src/Zend/zend_vm_execute.h:116212:12
    #8 0x55bdab77cac1 in zend_call_function /path/to/php-src/Zend/zend_execute_API.c:1014:3
    #9 0x55bdab3e45a5 in php_output_handler_op /path/to/php-src/main/output.c:970:19
    #10 0x55bdab3e34d0 in php_output_op /path/to/php-src/main/output.c:1113:4
    #11 0x55bdab3e3166 in php_output_write /path/to/php-src/main/output.c:240:3
    #12 0x55bdab3cdb51 in php_printf_unchecked /path/to/php-src/main/main.c:1034:8
    #13 0x55bdab3d4b96 in php_error_cb /path/to/php-src/main/main.c:1497:7
    #14 0x55bdabbd141a in zend_error_zstr_at /path/to/php-src/Zend/zend.c:1531:3
    #15 0x55bdabbd3791 in zend_error_va_list /path/to/php-src/Zend/zend.c:1633:2
    #16 0x55bdabbd3c88 in zend_error_unchecked /path/to/php-src/Zend/zend.c:1707:2
    #17 0x55bdab9d3bd2 in zval_undefined_cv /path/to/php-src/Zend/zend_execute.c:281:3
    #18 0x55bdab9d5fa0 in _get_zval_ptr_cv_BP_VAR_R /path/to/php-src/Zend/zend_execute.c:354:10
    #19 0x55bdab7f367a in ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DATA_CV_HANDLER /path/to/php-src/Zend/zend_vm_execute.h:45585:12
    #20 0x55bdab7a2492 in execute_ex /path/to/php-src/Zend/zend_vm_execute.h:116212:12
    #21 0x55bdab77cac1 in zend_call_function /path/to/php-src/Zend/zend_execute_API.c:1014:3
    #22 0x55bdab77ecd2 in zend_call_known_function /path/to/php-src/Zend/zend_execute_API.c:1108:23
    #23 0x55bdabb5205a in zend_call_known_instance_method /path/to/php-src/Zend/zend_API.h:862:2
    #24 0x55bdabb4f8bb in zend_call_known_instance_method_with_0_params /path/to/php-src/Zend/zend_API.h:868:2
    #25 0x55bdabb4f2b1 in zend_objects_destroy_object /path/to/php-src/Zend/zend_objects.c:172:3
    #26 0x55bdabb4ce12 in zend_objects_store_del /path/to/php-src/Zend/zend_objects_API.c:181:4
    #27 0x55bdabbb67d6 in rc_dtor_func /path/to/php-src/Zend/zend_variables.c:57:2
    #28 0x55bdab797a2c in zval_ptr_dtor_nogc /path/to/php-src/Zend/zend_variables.h:36:3
    #29 0x55bdab897800 in ZEND_FREE_SPEC_TMPVAR_HANDLER /path/to/php-src/Zend/zend_vm_execute.h:15675:2

previously allocated by thread T0 here:
    #0 0x55bdaa0861be in malloc (/path/to/php-src/sapi/cli/php+0x6861be) (BuildId: 78daf5f832c7fdbb3fc64cdca7de50663e951019)
    #1 0x55bdab6261b3 in __zend_malloc /path/to/php-src/Zend/zend_alloc.c:3543:14
    #2 0x55bdab625b40 in _emalloc /path/to/php-src/Zend/zend_alloc.c:2780:10
    #3 0x55bdaba3172b in zend_hash_packed_to_hash /path/to/php-src/Zend/zend_hash.c:357:13
    #4 0x55bdaba3f3a8 in _zend_hash_index_add_or_update_i /path/to/php-src/Zend/zend_hash.c:1161:4
    #5 0x55bdaba3fcd5 in zend_hash_index_lookup /path/to/php-src/Zend/zend_hash.c:1249:9
    #6 0x55bdab9d1a15 in zend_fetch_dimension_address_inner /path/to/php-src/Zend/zend_execute.c:2830:4
    #7 0x55bdab9da5cb in zend_fetch_dimension_address_inner_W_CONST /path/to/php-src/Zend/zend_execute.c:2892:9
    #8 0x55bdab7f35e2 in ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DATA_CV_HANDLER /path/to/php-src/Zend/zend_vm_execute.h:45578:20
    #9 0x55bdab7a2492 in execute_ex /path/to/php-src/Zend/zend_vm_execute.h:116212:12
    #10 0x55bdab77cac1 in zend_call_function /path/to/php-src/Zend/zend_execute_API.c:1014:3
    #11 0x55bdab77ecd2 in zend_call_known_function /path/to/php-src/Zend/zend_execute_API.c:1108:23
    #12 0x55bdabb5205a in zend_call_known_instance_method /path/to/php-src/Zend/zend_API.h:862:2
    #13 0x55bdabb4f8bb in zend_call_known_instance_method_with_0_params /path/to/php-src/Zend/zend_API.h:868:2
    #14 0x55bdabb4f2b1 in zend_objects_destroy_object /path/to/php-src/Zend/zend_objects.c:172:3
    #15 0x55bdabb4ce12 in zend_objects_store_del /path/to/php-src/Zend/zend_objects_API.c:181:4
    #16 0x55bdabbb67d6 in rc_dtor_func /path/to/php-src/Zend/zend_variables.c:57:2
    #17 0x55bdab797a2c in zval_ptr_dtor_nogc /path/to/php-src/Zend/zend_variables.h:36:3
    #18 0x55bdab897800 in ZEND_FREE_SPEC_TMPVAR_HANDLER /path/to/php-src/Zend/zend_vm_execute.h:15675:2
    #19 0x55bdab7a2492 in execute_ex /path/to/php-src/Zend/zend_vm_execute.h:116212:12
    #20 0x55bdab7a2d97 in zend_execute /path/to/php-src/Zend/zend_vm_execute.h:121924:2
    #21 0x55bdabbd65d0 in zend_execute_script /path/to/php-src/Zend/zend.c:1975:3
    #22 0x55bdab3d788b in php_execute_script_ex /path/to/php-src/main/main.c:2645:13
    #23 0x55bdab3d7d88 in php_execute_script /path/to/php-src/main/main.c:2685:9
    #24 0x55bdabbde4d2 in do_cli /path/to/php-src/sapi/cli/php_cli.c:951:5
    #25 0x55bdabbdb42c in main /path/to/php-src/sapi/cli/php_cli.c:1362:18
    #26 0x7f14f3b7ad8f  (/lib/x86_64-linux-gnu/libc.so.6+0x29d8f) (BuildId: 4f7b0c955c3d81d7cac1501a2498b69d1d82bfe7)

SUMMARY: AddressSanitizer: heap-use-after-free /path/to/php-src/Zend/zend_execute.h:195:7 in zend_assign_to_variable_ex
Shadow bytes around the buggy address:
  0x0c4c7fff9630: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c4c7fff9640: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c4c7fff9650: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c4c7fff9660: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c4c7fff9670: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
=>0x0c4c7fff9680: fd fd fd fd fd[fd]fd fd fd fd fd fd fd fd fd fd
  0x0c4c7fff9690: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c4c7fff96a0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c4c7fff96b0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c4c7fff96c0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c4c7fff96d0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
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
==3156334==ABORTING

Commit:

9cd367362da5442861f30d3b41e967d641b90cbd

Build configuration:

CC="clang" CXX="clang++" CFLAGS="-fsanitize=address -g -O0" CXXFLAGS="-fsanitize=address -g -O0" LDFLAGS="-fsanitize=address" ./buildconf --force && ./configure --enable-debug --enable-address-sanitizer --disable-shared --with-pic --enable-mbstring --with-zlib

PHP Version

PHP 8.6.0-dev (cli) (built: Nov 14 2025 16:07:53) (NTS DEBUG)
Copyright (c) The PHP Group
Zend Engine v4.6.0-dev, Copyright (c) Zend Technologies
    with Zend OPcache v8.6.0-dev, Copyright (c), by Zend Technologies

Operating System

Ubuntu 22.04

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