Skip to content

Crash when adding object to WeakMap during destruction #20404

@bwoebi

Description

@bwoebi

Description

The following code (simplified reproducer):

<?php

$w = new WeakMap;

$o = new stdClass;
$w[$o] = new class($r) {
    function __construct(public &$r) {}
    function __destruct() {
        global $refs;
        $o = $this->r->get();
        for ($i = 0; $i < 8; ++$i) {
            $r = new WeakMap;
            $r[$o] = 1;
            $refs[] = $r;
        }
    }
};
$r = WeakReference::create($o);

Resulted in this output:

==36773== Invalid read of size 1
==36773==    at 0x55C8198: zval_get_type (zend_types.h:648)
==36773==    by 0x55C78E7: zend_weakref_unref (/usr/local/src/php/Zend/zend_weakrefs.c:86)
==36773==    by 0x55C7783: zend_weakrefs_notify (/usr/local/src/php/Zend/zend_weakrefs.c:201)
==36773==    by 0x55DFDAF: zend_object_std_dtor (/usr/local/src/php/Zend/zend_objects.c:54)
==36773==    by 0x55EA76F: zend_objects_store_del (/usr/local/src/php/Zend/zend_objects_API.c:200)
==36773==    by 0x5499757: rc_dtor_func (/usr/local/src/php/Zend/zend_variables.c:57)
==36773==    by 0x54997F3: i_zval_ptr_dtor (zend_variables.h:44)
==36773==    by 0x5499793: zval_ptr_dtor (/usr/local/src/php/Zend/zend_variables.c:84)
==36773==    by 0x54BE46F: _zend_hash_del_el_ex (/usr/local/src/php/Zend/zend_hash.c:1488)
==36773==    by 0x54BDF6B: _zend_hash_del_el (/usr/local/src/php/Zend/zend_hash.c:1515)
==36773==    by 0x54C15C3: zend_hash_reverse_apply (/usr/local/src/php/Zend/zend_hash.c:2231)
==36773==    by 0x547A843: shutdown_destructors (/usr/local/src/php/Zend/zend_execute_API.c:260)
==36773==  Address 0xe812a58 is 104 bytes inside a block of size 320 free'd
==36773==    at 0x604B614: free (m_replacemalloc/vg_replace_malloc.c:989)
==36773==    by 0x544D673: _efree_custom (/usr/local/src/php/Zend/zend_alloc.c:2500)
==36773==    by 0x544D5C7: _efree (/usr/local/src/php/Zend/zend_alloc.c:2620)
==36773==    by 0x54C5D4F: zend_hash_do_resize (/usr/local/src/php/Zend/zend_hash.c:1316)
==36773==    by 0x54BD157: _zend_hash_index_add_or_update_i (/usr/local/src/php/Zend/zend_hash.c:1163)
==36773==    by 0x54BCACB: zend_hash_index_add_new (/usr/local/src/php/Zend/zend_hash.c:1211)
==36773==    by 0x55CA1EB: zend_hash_index_add_new_ptr (zend_hash.h:808)
==36773==    by 0x55C729F: zend_weakref_register (/usr/local/src/php/Zend/zend_weakrefs.c:110)
==36773==    by 0x55C9317: zend_weakmap_write_dimension (/usr/local/src/php/Zend/zend_weakrefs.c:385)
==36773==    by 0x5598AFB: zend_assign_to_object_dim (/usr/local/src/php/Zend/zend_execute.c:1535)
==36773==    by 0x55039EF: ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_CONST_HANDLER (zend_vm_execute.h:51937)
==36773==    by 0x54E2073: execute_ex (zend_vm_execute.h:57037)
==36773==  Block was alloc'd at
==36773==    at 0x60485D4: malloc (m_replacemalloc/vg_replace_malloc.c:446)
==36773==    by 0x544DA1B: __zend_malloc (/usr/local/src/php/Zend/zend_alloc.c:3128)
==36773==    by 0x544D54F: _malloc_custom (/usr/local/src/php/Zend/zend_alloc.c:2491)
==36773==    by 0x544D493: _emalloc (/usr/local/src/php/Zend/zend_alloc.c:2610)
==36773==    by 0x54B8887: zend_hash_real_init_mixed_ex (/usr/local/src/php/Zend/zend_hash.c:177)
==36773==    by 0x54B8787: zend_hash_real_init_mixed (/usr/local/src/php/Zend/zend_hash.c:343)
==36773==    by 0x54BD06F: _zend_hash_index_add_or_update_i (/usr/local/src/php/Zend/zend_hash.c:1150)
==36773==    by 0x54BCACB: zend_hash_index_add_new (/usr/local/src/php/Zend/zend_hash.c:1211)
==36773==    by 0x55CA1EB: zend_hash_index_add_new_ptr (zend_hash.h:808)
==36773==    by 0x55C72F3: zend_weakref_register (/usr/local/src/php/Zend/zend_weakrefs.c:117)
==36773==    by 0x55C8057: zend_weakref_create (/usr/local/src/php/Zend/zend_weakrefs.c:253)
==36773==    by 0x55C7CA7: zim_WeakReference_create (/usr/local/src/php/Zend/zend_weakrefs.c:291)

I.e. the cleanup in zend_weakref_unref() is not compatible with modifications during unref.

PHP Version

PHP 8.2+

Operating System

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions