Skip to content

Commit 7c2a4db

Browse files
authored
Replace ZEND_ASSUME() by ZEND_ASSERT() in zend_hash_*_ptr setters (#14466)
I had a case where I was intentionally storing a `NULL` pointer within a HashTable to mark an entry as “blocked”, without paying for the overhead of checking the entry type when reading the pointer, resulting in semantics that are similar to using `isset()` instead of `array_key_exists()` in userland. This worked fine in unoptimized test builds, but due to the `ZEND_ASSUME()` in the `zend_hash_find_ptr` functions, the optimized release builds turned the logic of: my_pointer = zend_hash_find_ptr(ht, key); if (my_pointer == NULL) { return; } *my_pointer; into zv = zend_hash_find(ht, key); if (zv) { *Z_PTR_P(zv); } else { return; } thus introducing a hard-to-debug and compiler-dependent crash when the entry exists, but the stored pointer is `NULL`. Change the `ZEND_ASSUME()` in the setters to `ZEND_ASSERT()`. This would have made my mistake immediately obvious in debug builds when storing the pointer. The getters still use `ZEND_ASSUME()` under the assumption that they are called much more often, reducing the impact on debug builds: Assuming the developer uses the `_ptr` variants for both reading and writing the entries, the mistake will be reliably caught during writing, making the assert during reading unnecessary. For release builds the `ZEND_ASSERT()` will be equivalent to `ZEND_ASSUME()`, avoiding any performance impact for those.
1 parent bda372f commit 7c2a4db

File tree

1 file changed

+8
-8
lines changed

1 file changed

+8
-8
lines changed

Zend/zend_hash.h

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -646,7 +646,7 @@ static zend_always_inline void *zend_hash_add_ptr(HashTable *ht, zend_string *ke
646646
ZVAL_PTR(&tmp, pData);
647647
zv = zend_hash_add(ht, key, &tmp);
648648
if (zv) {
649-
ZEND_ASSUME(Z_PTR_P(zv));
649+
ZEND_ASSERT(Z_PTR_P(zv));
650650
return Z_PTR_P(zv);
651651
} else {
652652
return NULL;
@@ -660,7 +660,7 @@ static zend_always_inline void *zend_hash_add_new_ptr(HashTable *ht, zend_string
660660
ZVAL_PTR(&tmp, pData);
661661
zv = zend_hash_add_new(ht, key, &tmp);
662662
if (zv) {
663-
ZEND_ASSUME(Z_PTR_P(zv));
663+
ZEND_ASSERT(Z_PTR_P(zv));
664664
return Z_PTR_P(zv);
665665
} else {
666666
return NULL;
@@ -674,7 +674,7 @@ static zend_always_inline void *zend_hash_str_add_ptr(HashTable *ht, const char
674674
ZVAL_PTR(&tmp, pData);
675675
zv = zend_hash_str_add(ht, str, len, &tmp);
676676
if (zv) {
677-
ZEND_ASSUME(Z_PTR_P(zv));
677+
ZEND_ASSERT(Z_PTR_P(zv));
678678
return Z_PTR_P(zv);
679679
} else {
680680
return NULL;
@@ -688,7 +688,7 @@ static zend_always_inline void *zend_hash_str_add_new_ptr(HashTable *ht, const c
688688
ZVAL_PTR(&tmp, pData);
689689
zv = zend_hash_str_add_new(ht, str, len, &tmp);
690690
if (zv) {
691-
ZEND_ASSUME(Z_PTR_P(zv));
691+
ZEND_ASSERT(Z_PTR_P(zv));
692692
return Z_PTR_P(zv);
693693
} else {
694694
return NULL;
@@ -701,7 +701,7 @@ static zend_always_inline void *zend_hash_update_ptr(HashTable *ht, zend_string
701701

702702
ZVAL_PTR(&tmp, pData);
703703
zv = zend_hash_update(ht, key, &tmp);
704-
ZEND_ASSUME(Z_PTR_P(zv));
704+
ZEND_ASSERT(Z_PTR_P(zv));
705705
return Z_PTR_P(zv);
706706
}
707707

@@ -711,7 +711,7 @@ static zend_always_inline void *zend_hash_str_update_ptr(HashTable *ht, const ch
711711

712712
ZVAL_PTR(&tmp, pData);
713713
zv = zend_hash_str_update(ht, str, len, &tmp);
714-
ZEND_ASSUME(Z_PTR_P(zv));
714+
ZEND_ASSERT(Z_PTR_P(zv));
715715
return Z_PTR_P(zv);
716716
}
717717

@@ -809,7 +809,7 @@ static zend_always_inline void *zend_hash_index_update_ptr(HashTable *ht, zend_u
809809

810810
ZVAL_PTR(&tmp, pData);
811811
zv = zend_hash_index_update(ht, h, &tmp);
812-
ZEND_ASSUME(Z_PTR_P(zv));
812+
ZEND_ASSERT(Z_PTR_P(zv));
813813
return Z_PTR_P(zv);
814814
}
815815

@@ -833,7 +833,7 @@ static zend_always_inline void *zend_hash_next_index_insert_ptr(HashTable *ht, v
833833
ZVAL_PTR(&tmp, pData);
834834
zv = zend_hash_next_index_insert(ht, &tmp);
835835
if (zv) {
836-
ZEND_ASSUME(Z_PTR_P(zv));
836+
ZEND_ASSERT(Z_PTR_P(zv));
837837
return Z_PTR_P(zv);
838838
} else {
839839
return NULL;

0 commit comments

Comments
 (0)