Skip to content

Commit

Permalink
Fix GH-12826: Weird pointers issue in nested loops
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
nielsdos committed Dec 1, 2023
1 parent c46fd35 commit b175ea4
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 1 deletion.
1 change: 1 addition & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ PHP NEWS
. Fix various missing NULL checks. (nielsdos, dstogov)
. Fixed bug GH-12835 (Leak of call->extra_named_params on internal __call).
(ilutov)
. Fixed bug GH-12826 (Weird pointers issue in nested loops). (nielsdos)

- FPM:
. Fixed bug GH-12705 (Segmentation fault in fpm_status_export_to_zval).
Expand Down
30 changes: 30 additions & 0 deletions Zend/tests/gh12826.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
--TEST--
GH-12826 (Weird pointers issue in nested loops)
--FILE--
<?php
$test = array(
'a' => 1,
'b' => 2,
'c' => 3,
'd' => 4,
);

unset($test['a']);
unset($test['b']);

foreach($test as $k => &$v) { // Mind the reference!
echo "Pass $k : ";

foreach($test as $kk => $vv) {
echo $test[$kk];
if ($kk == $k) $test[$kk] = 0;
}

echo "\n";
}

unset($v);
?>
--EXPECT--
Pass c : 34
Pass d : 04
2 changes: 1 addition & 1 deletion Zend/zend_hash.c
Original file line number Diff line number Diff line change
Expand Up @@ -2407,7 +2407,7 @@ static zend_always_inline uint32_t zend_array_dup_elements(HashTable *source, Ha
idx++; p++;
}
} else {
target->nNumUsed = source->nNumOfElements;
target->nNumUsed = source->nNumUsed;
uint32_t iter_pos = zend_hash_iterators_lower_pos(target, idx);

while (p != end) {
Expand Down

0 comments on commit b175ea4

Please sign in to comment.