Skip to content

Commit 975d28e

Browse files
committed
Fix GH-11222: foreach by-ref may jump over keys during a rehash
Signed-off-by: Bob Weinand <[email protected]>
1 parent 175ff60 commit 975d28e

File tree

3 files changed

+32
-1
lines changed

3 files changed

+32
-1
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ PHP NEWS
88
. Fixed bug GH-11189 (Exceeding memory limit in zend_hash_do_resize leaves
99
the array in an invalid state). (Bob)
1010
. Fixed bug GH-11063 (Compilation error on old GCC versions). (ingamedeo)
11+
. Fixed bug GH-11222 (foreach by-ref may jump over keys during a rehash).
12+
(Bob)
1113

1214
- Hash:
1315
. Fixed bug GH-11180 (hash_file() appears to be restricted to 3 arguments).

Zend/tests/gh11222.phpt

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
--TEST--
2+
GH-112222: foreach by-ref may jump over keys during a rehash
3+
--FILE--
4+
<?php
5+
6+
// Not packed
7+
$a = ["k" => 0, 1 => 1, 2, 3, 4, 5, 6];
8+
foreach ($a as $k => &$v) {
9+
if ($k == 1) {
10+
// force that it'll be rehashed by adding enough holes
11+
unset($a[4], $a[5]);
12+
// actually make the array larger than 8 elements to trigger rehash
13+
$a[] = 8; $a[] = 9; $a[] = 10;
14+
15+
}
16+
// observe the iteration jumping from key 1 to key 6, skipping keys 2 and 3
17+
echo "$k => $v\n";
18+
}
19+
20+
?>
21+
--EXPECTF--
22+
k => 0
23+
1 => 1
24+
2 => 2
25+
3 => 3
26+
6 => 6
27+
7 => 8
28+
8 => 9
29+
9 => 10

Zend/zend_hash.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1282,7 +1282,7 @@ ZEND_API void ZEND_FASTCALL zend_hash_rehash(HashTable *ht)
12821282
}
12831283
}
12841284
} else {
1285-
uint32_t iter_pos = zend_hash_iterators_lower_pos(ht, 0);
1285+
uint32_t iter_pos = zend_hash_iterators_lower_pos(ht, i + 1);
12861286

12871287
while (++i < ht->nNumUsed) {
12881288
p++;

0 commit comments

Comments
 (0)