Crash when adding object to WeakMap during destruction
Abierto
Nadie ha tomado este issue todavía.
Bug
Status: Verified
- Lenguaje dominante
- C
- Estrellas
- 40.4k
- Forks
- 8.1k
- Merge medio
- 2 d 13 h
- PR fusionados (30 d)
- 96
Descripción
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
Guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Línea de trabajo
Comienza con el reproductor e inspecciona zend_weakref_unref() y las rutas relacionadas de registro y notificación en zend_weakrefs.c; utiliza el seguimiento de Valgrind para seguir la lectura no válida durante la destrucción. La tarea estará terminada cuando el reproductor ya no informe de una lectura no válida al añadir entradas de WeakMap durante la destrucción.
Escrito por el modelo de indexación a partir del texto del issue.
Evaluación
- Stack tecnológico
- c, php
- Área
- backend
- Tipo de issue
- Error
- Dificultad
- 4/5
- Tiempo estimado
- 3-5 días
- Estado de actividad
- Estancado
- Claridad
- Bien especificado
- Aptitud para principiantes
- 45/100