From 3bc4a63fc27768c665fcbc101db4e579c761833b Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 14 Sep 2018 10:28:31 +0300 Subject: Fixed bug #76800 (foreach inconsistent if array modified during loop) --- NEWS | 4 ++++ Zend/tests/bug76800.phpt | 13 +++++++++++++ Zend/zend_hash.c | 8 +++++--- 3 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 Zend/tests/bug76800.phpt diff --git a/NEWS b/NEWS index 8e9468e15d..952182f2cf 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? 2018, PHP 7.2.11 +- Core: + . Fixed bug #76800 (foreach inconsistent if array modified during loop). + (Dmitry) + - Opcache: . Fixed bug #76832 (ZendOPcache.MemoryBase periodically deleted by the OS). (Anatol) diff --git a/Zend/tests/bug76800.phpt b/Zend/tests/bug76800.phpt new file mode 100644 index 0000000000..d7f6d8070b --- /dev/null +++ b/Zend/tests/bug76800.phpt @@ -0,0 +1,13 @@ +--TEST-- +Bug #76800 (foreach inconsistent if array modified during loop) +--FILE-- + 1, 3 => 3]; // [1 => 1, 2 => 3] will print both keys +foreach($arr as $key => &$val) { // without & will print both keys + echo "See key {$key}\n"; + $arr[0] = 0; // without this line will print both keys + unset($arr[0]); +} +--EXPECT-- +See key 1 +See key 3 diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index f1b0c9b86c..80938694e5 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -932,9 +932,11 @@ ZEND_API int ZEND_FASTCALL zend_hash_rehash(HashTable *ht) if (UNEXPECTED(ht->nInternalPointer == i)) { ht->nInternalPointer = j; } - if (UNEXPECTED(i == iter_pos)) { - zend_hash_iterators_update(ht, i, j); - iter_pos = zend_hash_iterators_lower_pos(ht, iter_pos + 1); + if (UNEXPECTED(i >= iter_pos)) { + do { + zend_hash_iterators_update(ht, iter_pos, j); + iter_pos = zend_hash_iterators_lower_pos(ht, iter_pos + 1); + } while (iter_pos < i); } q++; j++; -- cgit v1.2.1