]> granicus.if.org Git - php/commitdiff
Fixed bug #76800 (foreach inconsistent if array modified during loop)
authorDmitry Stogov <dmitry@zend.com>
Fri, 14 Sep 2018 07:28:31 +0000 (10:28 +0300)
committerDmitry Stogov <dmitry@zend.com>
Fri, 14 Sep 2018 07:28:31 +0000 (10:28 +0300)
NEWS
Zend/tests/bug76800.phpt [new file with mode: 0644]
Zend/zend_hash.c

diff --git a/NEWS b/NEWS
index 8e9468e15d127fc417ae2ad325d4de06cdedf166..952182f2cf4747188b7c941caf1bc7c2ce127fbc 100644 (file)
--- 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 (file)
index 0000000..d7f6d80
--- /dev/null
@@ -0,0 +1,13 @@
+--TEST--
+Bug #76800 (foreach inconsistent if array modified during loop)
+--FILE--
+<?php
+$arr = [1 => 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
index f1b0c9b86cea5166a88f0ee4fbaf6e76cb728c49..80938694e55025634add1490d67f04479b3688f1 100644 (file)
@@ -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++;