Skip to content

Commit b175ea4

Browse files
committed
Fix GH-12826: Weird pointers issue in nested loops
This regressed in cd53ce8. The loop with `zend_hash_iterators_update` hangs forever because `iter_pos` can't advance to idx. This is because the `zend_hash_iterators_lower_pos` upper bound is `target->nNumUsed`, but that is set to `source->nNumOfElements`. That means that if there are holes in the array, we still loop over all the buckets but the number of bucket slots will not match. Fix it by changing the assignment. Closes GH-12831.
1 parent c46fd35 commit b175ea4

File tree

3 files changed

+32
-1
lines changed

3 files changed

+32
-1
lines changed

NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ PHP NEWS
88
. Fix various missing NULL checks. (nielsdos, dstogov)
99
. Fixed bug GH-12835 (Leak of call->extra_named_params on internal __call).
1010
(ilutov)
11+
. Fixed bug GH-12826 (Weird pointers issue in nested loops). (nielsdos)
1112

1213
- FPM:
1314
. Fixed bug GH-12705 (Segmentation fault in fpm_status_export_to_zval).

Zend/tests/gh12826.phpt

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
--TEST--
2+
GH-12826 (Weird pointers issue in nested loops)
3+
--FILE--
4+
<?php
5+
$test = array(
6+
'a' => 1,
7+
'b' => 2,
8+
'c' => 3,
9+
'd' => 4,
10+
);
11+
12+
unset($test['a']);
13+
unset($test['b']);
14+
15+
foreach($test as $k => &$v) { // Mind the reference!
16+
echo "Pass $k : ";
17+
18+
foreach($test as $kk => $vv) {
19+
echo $test[$kk];
20+
if ($kk == $k) $test[$kk] = 0;
21+
}
22+
23+
echo "\n";
24+
}
25+
26+
unset($v);
27+
?>
28+
--EXPECT--
29+
Pass c : 34
30+
Pass d : 04

Zend/zend_hash.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2407,7 +2407,7 @@ static zend_always_inline uint32_t zend_array_dup_elements(HashTable *source, Ha
24072407
idx++; p++;
24082408
}
24092409
} else {
2410-
target->nNumUsed = source->nNumOfElements;
2410+
target->nNumUsed = source->nNumUsed;
24112411
uint32_t iter_pos = zend_hash_iterators_lower_pos(target, idx);
24122412

24132413
while (p != end) {

0 commit comments

Comments
 (0)