summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS2
-rw-r--r--Zend/tests/bug76800.phpt13
-rw-r--r--Zend/zend_hash.c8
3 files changed, 20 insertions, 3 deletions
diff --git a/NEWS b/NEWS
index c99e0fd17a..2110d48f92 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,8 @@ PHP NEWS
- Core:
. Fixed bug #76869 (Incorrect bypassing protected method accessibilty check).
(Dmitry)
+ . Fixed bug #76800 (foreach inconsistent if array modified during loop).
+ (Dmitry)
13 Sep 2018, PHP 7.3.0RC1
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--
+<?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
diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c
index 3a8815336d..3d5da267c4 100644
--- a/Zend/zend_hash.c
+++ b/Zend/zend_hash.c
@@ -1114,9 +1114,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++;