1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 08:12:21 +01:00

Merge branch 'PHP-8.4' into PHP-8.5

* PHP-8.4:
  Fix GH-19926: reset internal pointer earlier while splicing array while COW violation flag is still set (#19929)
This commit is contained in:
Alexandre Daubois
2025-10-06 16:53:45 +02:00
4 changed files with 47 additions and 2 deletions

2
NEWS
View File

@@ -103,6 +103,8 @@ PHP NEWS
(alexandre-daubois)
. Fixed GH-14402 (SplPriorityQueue, SplMinHeap, and SplMaxHeap lost their
data on serialize()). (alexandre-daubois)
. Fixed bug GH-19926 (reset internal pointer earlier while splicing array
while COW violation flag is still set). (alexandre-daubois)
- URI:
. Fixed bug GH-19780 (InvalidUrlException should check $errors argument).

View File

@@ -3489,6 +3489,12 @@ static void php_splice(HashTable *in_hash, zend_long offset, zend_long length, H
HT_SET_ITERATORS_COUNT(in_hash, 0);
in_hash->pDestructor = NULL;
/* Set internal pointer to 0 directly instead of calling zend_hash_internal_pointer_reset().
* This avoids the COW violation assertion and delays advancing to the first valid position
* until after we've switched to the new array structure (out_hash). The iterator will be
* advanced when actually accessed, at which point it will find valid indexes in the new array. */
in_hash->nInternalPointer = 0;
if (UNEXPECTED(GC_DELREF(in_hash) == 0)) {
/* Array was completely deallocated during the operation */
zend_array_destroy(in_hash);
@@ -3507,8 +3513,6 @@ static void php_splice(HashTable *in_hash, zend_long offset, zend_long length, H
in_hash->nNextFreeElement = out_hash.nNextFreeElement;
in_hash->arData = out_hash.arData;
in_hash->pDestructor = out_hash.pDestructor;
zend_hash_internal_pointer_reset(in_hash);
}
/* }}} */

View File

@@ -0,0 +1,20 @@
--TEST--
GH-19926 (Assertion failure zend_hash_internal_pointer_reset_ex)
--FILE--
<?php
class ThrowingDestructor {
function __destruct() {
throw new Exception();
}
}
$arr = [new ThrowingDestructor(), new ThrowingDestructor()];
try {
array_splice($arr, 0, 2);
} catch (Exception $e) {
echo "Exception caught, no assertion failure\n";
}
?>
--EXPECT--
Exception caught, no assertion failure

View File

@@ -0,0 +1,19 @@
--TEST--
GH-19926 (internal pointer behavior after array_splice)
--FILE--
<?php
$a = [1, 2, 3];
unset($a[0]);
next($a);
echo "Before array_splice: ";
var_dump(current($a));
array_splice($a, 0, 0, [999]);
echo "After array_splice: ";
var_dump(current($a));
?>
--EXPECT--
Before array_splice: int(3)
After array_splice: int(999)