@@ -1331,6 +1331,18 @@ ZEND_API void ZEND_FASTCALL zend_hash_rehash(HashTable *ht)
13311331 if (!(HT_FLAGS (ht ) & HASH_FLAG_UNINITIALIZED )) {
13321332 ht -> nNumUsed = 0 ;
13331333 HT_HASH_RESET (ht );
1334+ /* Even if the array is empty, we still need to reset the iterator positions. */
1335+ ht -> nInternalPointer = 0 ;
1336+ if (UNEXPECTED (HT_HAS_ITERATORS (ht ))) {
1337+ HashTableIterator * iter = EG (ht_iterators );
1338+ HashTableIterator * end = iter + EG (ht_iterators_used );
1339+ while (iter != end ) {
1340+ if (iter -> ht == ht ) {
1341+ iter -> pos = 0 ;
1342+ }
1343+ iter ++ ;
1344+ }
1345+ }
13341346 }
13351347 return ;
13361348 }
@@ -1412,32 +1424,30 @@ ZEND_API void ZEND_FASTCALL zend_hash_rehash(HashTable *ht)
14121424 }
14131425}
14141426
1415- static zend_always_inline void _zend_hash_packed_del_val (HashTable * ht , uint32_t idx , zval * zv )
1427+ static zend_always_inline void zend_hash_iterators_clamp_max (HashTable * ht , uint32_t max )
14161428{
1417- idx = HT_HASH_TO_IDX (idx );
1418- ht -> nNumOfElements -- ;
1419- if (ht -> nInternalPointer == idx || UNEXPECTED (HT_HAS_ITERATORS (ht ))) {
1420- uint32_t new_idx ;
1421-
1422- new_idx = idx ;
1423- while (1 ) {
1424- new_idx ++ ;
1425- if (new_idx >= ht -> nNumUsed ) {
1426- break ;
1427- } else if (Z_TYPE (ht -> arPacked [new_idx ]) != IS_UNDEF ) {
1428- break ;
1429+ if (UNEXPECTED (HT_HAS_ITERATORS (ht ))) {
1430+ HashTableIterator * iter = EG (ht_iterators );
1431+ HashTableIterator * end = iter + EG (ht_iterators_used );
1432+ while (iter != end ) {
1433+ if (iter -> ht == ht ) {
1434+ iter -> pos = MIN (iter -> pos , max );
14291435 }
1436+ iter ++ ;
14301437 }
1431- if (ht -> nInternalPointer == idx ) {
1432- ht -> nInternalPointer = new_idx ;
1433- }
1434- zend_hash_iterators_update (ht , idx , new_idx );
14351438 }
1439+ }
1440+
1441+ static zend_always_inline void _zend_hash_packed_del_val (HashTable * ht , uint32_t idx , zval * zv )
1442+ {
1443+ idx = HT_HASH_TO_IDX (idx );
1444+ ht -> nNumOfElements -- ;
14361445 if (ht -> nNumUsed - 1 == idx ) {
14371446 do {
14381447 ht -> nNumUsed -- ;
14391448 } while (ht -> nNumUsed > 0 && (UNEXPECTED (Z_TYPE (ht -> arPacked [ht -> nNumUsed - 1 ]) == IS_UNDEF )));
14401449 ht -> nInternalPointer = MIN (ht -> nInternalPointer , ht -> nNumUsed );
1450+ zend_hash_iterators_clamp_max (ht , ht -> nNumUsed );
14411451 }
14421452 if (ht -> pDestructor ) {
14431453 zval tmp ;
@@ -1458,28 +1468,12 @@ static zend_always_inline void _zend_hash_del_el_ex(HashTable *ht, uint32_t idx,
14581468 }
14591469 idx = HT_HASH_TO_IDX (idx );
14601470 ht -> nNumOfElements -- ;
1461- if (ht -> nInternalPointer == idx || UNEXPECTED (HT_HAS_ITERATORS (ht ))) {
1462- uint32_t new_idx ;
1463-
1464- new_idx = idx ;
1465- while (1 ) {
1466- new_idx ++ ;
1467- if (new_idx >= ht -> nNumUsed ) {
1468- break ;
1469- } else if (Z_TYPE (ht -> arData [new_idx ].val ) != IS_UNDEF ) {
1470- break ;
1471- }
1472- }
1473- if (ht -> nInternalPointer == idx ) {
1474- ht -> nInternalPointer = new_idx ;
1475- }
1476- zend_hash_iterators_update (ht , idx , new_idx );
1477- }
14781471 if (ht -> nNumUsed - 1 == idx ) {
14791472 do {
14801473 ht -> nNumUsed -- ;
14811474 } while (ht -> nNumUsed > 0 && (UNEXPECTED (Z_TYPE (ht -> arData [ht -> nNumUsed - 1 ].val ) == IS_UNDEF )));
14821475 ht -> nInternalPointer = MIN (ht -> nInternalPointer , ht -> nNumUsed );
1476+ zend_hash_iterators_clamp_max (ht , ht -> nNumUsed );
14831477 }
14841478 if (ht -> pDestructor ) {
14851479 zval tmp ;
0 commit comments