Skip to content

Commit 4985d41

Browse files
Fix GH-19926: preserve COW violation flags when copying a hashtable while splicing
1 parent 266cb7d commit 4985d41

File tree

2 files changed

+30
-2
lines changed

2 files changed

+30
-2
lines changed

ext/standard/array.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3376,6 +3376,9 @@ static void php_splice(HashTable *in_hash, zend_long offset, zend_long length, H
33763376
HT_SET_ITERATORS_COUNT(in_hash, 0);
33773377
in_hash->pDestructor = NULL;
33783378

3379+
/* Reset internal pointer while COW violation flag is still set */
3380+
zend_hash_internal_pointer_reset(in_hash);
3381+
33793382
if (UNEXPECTED(GC_DELREF(in_hash) == 0)) {
33803383
/* Array was completely deallocated during the operation */
33813384
zend_array_destroy(in_hash);
@@ -3394,8 +3397,6 @@ static void php_splice(HashTable *in_hash, zend_long offset, zend_long length, H
33943397
in_hash->nNextFreeElement = out_hash.nNextFreeElement;
33953398
in_hash->arData = out_hash.arData;
33963399
in_hash->pDestructor = out_hash.pDestructor;
3397-
3398-
zend_hash_internal_pointer_reset(in_hash);
33993400
}
34003401
/* }}} */
34013402

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
--TEST--
2+
GH-19926 (Assertion failure zend_hash_internal_pointer_reset_ex)
3+
--FILE--
4+
<?php
5+
function exception_error_handler() {
6+
throw new Exception();
7+
}
8+
9+
set_error_handler("exception_error_handler");
10+
11+
class MultiDestructor {
12+
function __destruct() {
13+
if ($this->id == 2) {
14+
}
15+
}
16+
}
17+
18+
$arr = ["start", new MultiDestructor(1), new MultiDestructor(2), "end"];
19+
20+
try {
21+
array_splice($arr, 1, 2);
22+
} catch (Exception $e) {
23+
echo "Exception caught, no assertion failure\n";
24+
}
25+
?>
26+
--EXPECT--
27+
Exception caught, no assertion failure

0 commit comments

Comments
 (0)