diff --git a/Zend/tests/gh19613.phpt b/Zend/tests/gh19613.phpt new file mode 100644 index 0000000000000..cd8360b681c79 --- /dev/null +++ b/Zend/tests/gh19613.phpt @@ -0,0 +1,22 @@ +--TEST-- +GH-19613: Invalidated array iterator pointer after array separation +--FILE-- + +--EXPECT-- +===DONE=== diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index 90a36efd2b981..07d5bed6d7655 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -630,8 +630,15 @@ ZEND_API HashPosition ZEND_FASTCALL zend_hash_iterator_pos_ex(uint32_t idx, zval && EXPECTED(!HT_ITERATORS_OVERFLOW(ht))) { HT_DEC_ITERATORS_COUNT(iter->ht); } - SEPARATE_ARRAY(array); - ht = Z_ARRVAL_P(array); + + /* Inlined SEPARATE_ARRAY() with updating of iterator when EG(ht_iterators) grows. */ + if (UNEXPECTED(GC_REFCOUNT(ht) > 1)) { + ZVAL_ARR(array, zend_array_dup(ht)); + GC_TRY_DELREF(ht); + iter = EG(ht_iterators) + idx; + ht = Z_ARRVAL_P(array); + } + if (EXPECTED(!HT_ITERATORS_OVERFLOW(ht))) { HT_INC_ITERATORS_COUNT(ht); }