Commit 28fc06be490 for php.net

commit 28fc06be4908c7763e16c9addc4f3bb2bfb4c450
Author: Tim Düsterhus <tim@tideways-gmbh.com>
Date:   Tue Sep 16 10:51:07 2025 +0200

    zend_hash: Assert that the `interned` parameter is not a lie (#19843)

    * zend_hash: Assert that the `interned` parameter is not a lie

    While investigating php/php-src#19842 I was wondering why non-interned string
    didn't cause troubles, until I realized it was the value instead of the key.
    Nevertheless it appears useful to check that the key is actually interned as
    claimed by the caller to prevent hard-to-find bugs.

    * zend_hash: Rename `interned` parameter name to `key_guaranteed_interned`

diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h
index 71206e61550..57020bbcad0 100644
--- a/Zend/zend_hash.h
+++ b/Zend/zend_hash.h
@@ -1621,14 +1621,15 @@ static zend_always_inline bool zend_array_is_list(const zend_array *array)
 }


-static zend_always_inline zval *_zend_hash_append_ex(HashTable *ht, zend_string *key, zval *zv, bool interned)
+static zend_always_inline zval *_zend_hash_append_ex(HashTable *ht, zend_string *key, zval *zv, bool key_guaranteed_interned)
 {
 	uint32_t idx = ht->nNumUsed++;
 	uint32_t nIndex;
 	Bucket *p = ht->arData + idx;

 	ZVAL_COPY_VALUE(&p->val, zv);
-	if (!interned && !ZSTR_IS_INTERNED(key)) {
+	ZEND_ASSERT(!key_guaranteed_interned || ZSTR_IS_INTERNED(key));
+	if (!key_guaranteed_interned && !ZSTR_IS_INTERNED(key)) {
 		HT_FLAGS(ht) &= ~HASH_FLAG_STATIC_KEYS;
 		zend_string_addref(key);
 		zend_string_hash_val(key);
@@ -1647,14 +1648,15 @@ static zend_always_inline zval *_zend_hash_append(HashTable *ht, zend_string *ke
 	return _zend_hash_append_ex(ht, key, zv, 0);
 }

-static zend_always_inline zval *_zend_hash_append_ptr_ex(HashTable *ht, zend_string *key, void *ptr, bool interned)
+static zend_always_inline zval *_zend_hash_append_ptr_ex(HashTable *ht, zend_string *key, void *ptr, bool key_guaranteed_interned)
 {
 	uint32_t idx = ht->nNumUsed++;
 	uint32_t nIndex;
 	Bucket *p = ht->arData + idx;

 	ZVAL_PTR(&p->val, ptr);
-	if (!interned && !ZSTR_IS_INTERNED(key)) {
+	ZEND_ASSERT(!key_guaranteed_interned || ZSTR_IS_INTERNED(key));
+	if (!key_guaranteed_interned && !ZSTR_IS_INTERNED(key)) {
 		HT_FLAGS(ht) &= ~HASH_FLAG_STATIC_KEYS;
 		zend_string_addref(key);
 		zend_string_hash_val(key);