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..b05ad1d32fe4 --- /dev/null +++ b/Zend/tests/weakrefs/weakmap_temporary_key_by_ref.phpt @@ -0,0 +1,61 @@ +--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 +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));