Skip to content

Commit f1fc4e8

Browse files
committed
Fix GH-16957: Assertion failure in array_shift with self-referencing array
We have an RC1 violation because we're immediately dereferencing and copying the resulting array in the test case. Instead, transfer the lifetime using RETVAL_COPY_VALUE and unwrap only after the internal iterator is reset. Closes GH-16970.
1 parent a4874bb commit f1fc4e8

File tree

3 files changed

+51
-2
lines changed

3 files changed

+51
-2
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ PHP NEWS
7676
- Standard:
7777
. Fixed bug GH-16905 (Internal iterator functions can't handle UNDEF
7878
properties). (nielsdos)
79+
. Fixed bug GH-16957 (Assertion failure in array_shift with
80+
self-referencing array). (nielsdos)
7981

8082
- Streams:
8183
. Fixed network connect poll interuption handling. (Jakub Zelenka)

ext/standard/array.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3511,7 +3511,8 @@ PHP_FUNCTION(array_shift)
35113511
}
35123512
idx++;
35133513
}
3514-
RETVAL_COPY_DEREF(val);
3514+
RETVAL_COPY_VALUE(val);
3515+
ZVAL_UNDEF(val);
35153516

35163517
/* Delete the first value */
35173518
zend_hash_packed_del_val(Z_ARRVAL_P(stack), val);
@@ -3565,7 +3566,8 @@ PHP_FUNCTION(array_shift)
35653566
}
35663567
idx++;
35673568
}
3568-
RETVAL_COPY_DEREF(val);
3569+
RETVAL_COPY_VALUE(val);
3570+
ZVAL_UNDEF(val);
35693571

35703572
/* Delete the first value */
35713573
zend_hash_del_bucket(Z_ARRVAL_P(stack), p);
@@ -3589,6 +3591,10 @@ PHP_FUNCTION(array_shift)
35893591
}
35903592

35913593
zend_hash_internal_pointer_reset(Z_ARRVAL_P(stack));
3594+
3595+
if (Z_ISREF_P(return_value)) {
3596+
zend_unwrap_reference(return_value);
3597+
}
35923598
}
35933599
/* }}} */
35943600

ext/standard/tests/array/gh16957.phpt

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
--TEST--
2+
GH-16957 (Assertion failure in array_shift with self-referencing array)
3+
--FILE--
4+
<?php
5+
$new_array = array(&$new_array, 1, 'two');
6+
var_dump($shifted = array_shift($new_array));
7+
var_dump($new_array);
8+
var_dump($new_array === $shifted);
9+
10+
$new_array2 = array(&$new_array2, 2 => 1, 300 => 'two');
11+
var_dump($shifted = array_shift($new_array2));
12+
var_dump($new_array2);
13+
var_dump($new_array2 === $shifted);
14+
?>
15+
--EXPECT--
16+
array(2) {
17+
[0]=>
18+
int(1)
19+
[1]=>
20+
string(3) "two"
21+
}
22+
array(2) {
23+
[0]=>
24+
int(1)
25+
[1]=>
26+
string(3) "two"
27+
}
28+
bool(true)
29+
array(2) {
30+
[0]=>
31+
int(1)
32+
[1]=>
33+
string(3) "two"
34+
}
35+
array(2) {
36+
[0]=>
37+
int(1)
38+
[1]=>
39+
string(3) "two"
40+
}
41+
bool(true)

0 commit comments

Comments
 (0)