php / php/php-src

Crash when adding object to WeakMap during destruction

Offen
#20,404 0 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

Bug Status: Verified
Vorherrschende Sprache
C
Sterne
40.4k
Forks
8.1k
Ø Merge
2 T. 13 Std.
Gemergte PRs (30 T.)
96

Beschreibung

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

Beitragsleitfaden

Beitragsleitfaden öffnen

Erste Schritte

  1. Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
  3. Forke das Repository und arbeite in einem Branch.
  4. Öffne einen Pull Request, der die Issue-Nummer nennt.

Rechercherichtung

Beginne mit dem Reproducer und untersuche zend_weakref_unref() sowie die zugehörigen Registrierungs- und Benachrichtigungspfade in zend_weakrefs.c; verwende den Valgrind-Trace, um den ungültigen Lesezugriff während der Zerstörung nachzuverfolgen. Die Aufgabe ist erledigt, wenn der Reproducer keinen ungültigen Lesezugriff mehr meldet, wenn während der Zerstörung WeakMap-Einträge hinzugefügt werden.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
c, php
Bereich
backend
Issue-Typ
Bug
Schwierigkeit
4/5
Geschätzter Aufwand
3-5 Tage
Aktivitätsstatus
Veraltet
Klarheit
Klar beschrieben
Anfängerfreundlichkeit
45/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.