diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index 6668c4c17c66..ea1bfa3afc0f 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -2346,17 +2346,20 @@ static zend_always_inline bool zend_array_dup_element(HashTable *source, HashTab // We need to duplicate iterators to be able to search through all copy-on-write copies to find the actually iterated HashTable and position back static void zend_array_dup_ht_iterators(HashTable *source, HashTable *target) { - HashTableIterator *iter = EG(ht_iterators); - HashTableIterator *end = iter + EG(ht_iterators_used); + uint32_t iter_index = 0; + uint32_t end_index = EG(ht_iterators_used); - while (iter != end) { + while (iter_index != end_index) { + HashTableIterator *iter = &EG(ht_iterators)[iter_index]; if (iter->ht == source) { uint32_t copy_idx = zend_hash_iterator_add(target, iter->pos); + /* Refetch iter because the memory may be reallocated. */ + iter = &EG(ht_iterators)[iter_index]; HashTableIterator *copy_iter = EG(ht_iterators) + copy_idx; copy_iter->next_copy = iter->next_copy; iter->next_copy = copy_idx; } - iter++; + iter_index++; } } diff --git a/ext/spl/tests/gh16054.phpt b/ext/spl/tests/gh16054.phpt new file mode 100644 index 000000000000..cef6e547afbf --- /dev/null +++ b/ext/spl/tests/gh16054.phpt @@ -0,0 +1,15 @@ +--TEST-- +GH-16054 (Segmentation fault when resizing hash table iterator list while adding) +--FILE-- + $v) { + if (++$counter > 200) break; +} +echo "ok\n"; +?> +--EXPECT-- +ok