From d92eaf02f9c21757e9d235079693a74558e29918 Mon Sep 17 00:00:00 2001 From: Alessio Attilio Date: Wed, 11 Nov 2026 17:41:47 +0100 Subject: [PATCH 1/2] Fix WeakMap temporary key dimension fetch --- .../weakmap_temporary_key_by_ref.phpt | 63 +++++++++++++++++++ Zend/zend_weakrefs.c | 11 ++++ 2 files changed, 74 insertions(+) create mode 100644 Zend/tests/weakrefs/weakmap_temporary_key_by_ref.phpt diff --git a/Zend/tests/weakrefs/weakmap_temporary_key_by_ref.phpt b/Zend/tests/weakrefs/weakmap_temporary_key_by_ref.phpt new file mode 100644 index 000000000000..1b7d22eea638 --- /dev/null +++ b/Zend/tests/weakrefs/weakmap_temporary_key_by_ref.phpt @@ -0,0 +1,63 @@ +--TEST-- +WeakMap dimension reference with a temporary key +--FILE-- +getMessage(), "\n"; +} +var_dump(count($wm)); + +try { + $wm[new stdClass][] = 1; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +var_dump(count($wm)); + +$key = new stdClass; +$wm[$key] = 2; +$keys = [$key]; +$r = &$wm[array_pop($keys)]; +$r = 3; +var_dump($wm[$key]); + +$key = new stdClass; +$wm[$key] = 1; +$keys = [$key]; +unset($key); +try { + $r = &$wm[array_pop($keys)]; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +var_dump(count($wm)); + +class K { + function __destruct() { + $GLOBALS['wm'] = null; + } +} + +$wm = new WeakMap; +try { + $wm[new K][] = str_repeat("x", 10); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +var_dump($wm); +?> +--EXPECT-- +Cannot modify a WeakMap dimension using a temporary object key +int(0) +Cannot modify a WeakMap dimension using a temporary object key +int(0) +int(3) +Cannot modify a WeakMap dimension using a temporary object key +int(0) +Cannot modify a WeakMap dimension using a temporary object key +int(0) +Cannot modify a WeakMap dimension using a temporary object key +NULL diff --git a/Zend/zend_weakrefs.c b/Zend/zend_weakrefs.c index 1d669771a550..13acff4d57a5 100644 --- a/Zend/zend_weakrefs.c +++ b/Zend/zend_weakrefs.c @@ -354,6 +354,8 @@ static void zend_weakmap_free_obj(zend_object *object) static zval *zend_weakmap_read_dimension(zend_object *object, zval *offset, int type, zval *rv) { + zval *orig_offset = offset; + if (offset == NULL) { zend_throw_error(NULL, "Cannot append to WeakMap"); return NULL; @@ -369,6 +371,15 @@ static zval *zend_weakmap_read_dimension(zend_object *object, zval *offset, int zend_object *obj_addr = Z_OBJ_P(offset); zval *zv = zend_hash_index_find(&wm->ht, zend_object_to_weakref_key(obj_addr)); if (type == BP_VAR_W || type == BP_VAR_RW) { + const zend_execute_data *ex = EG(current_execute_data); + if (UNEXPECTED(GC_REFCOUNT(obj_addr) == 1) + && ex && ex->func && ZEND_USER_CODE(ex->func->type) + && ex->opline + && (ex->opline->op2_type & (IS_TMP_VAR | IS_VAR)) + && orig_offset == ZEND_CALL_VAR(ex, ex->opline->op2.var)) { + zend_throw_error(NULL, "Cannot modify a WeakMap dimension using a temporary object key"); + return NULL; + } if (zv == NULL) { zval value; zend_weakref_register(obj_addr, ZEND_WEAKREF_ENCODE(&wm->ht, ZEND_WEAKREF_TAG_MAP)); From c274be28cd001d98db5af15ada54fca934ff7c18 Mon Sep 17 00:00:00 2001 From: Alessio Attilio Date: Wed, 11 Nov 2026 19:13:12 +0100 Subject: [PATCH 2/2] Fix WeakMap temporary key test expectation --- Zend/tests/weakrefs/weakmap_temporary_key_by_ref.phpt | 2 -- 1 file changed, 2 deletions(-) diff --git a/Zend/tests/weakrefs/weakmap_temporary_key_by_ref.phpt b/Zend/tests/weakrefs/weakmap_temporary_key_by_ref.phpt index 1b7d22eea638..b05ad1d32fe4 100644 --- a/Zend/tests/weakrefs/weakmap_temporary_key_by_ref.phpt +++ b/Zend/tests/weakrefs/weakmap_temporary_key_by_ref.phpt @@ -58,6 +58,4 @@ int(3) Cannot modify a WeakMap dimension using a temporary object key int(0) Cannot modify a WeakMap dimension using a temporary object key -int(0) -Cannot modify a WeakMap dimension using a temporary object key NULL