Skip to content

Commit 7ccd594

Browse files
committed
Fixed bug #61730 (Segfault from array_walk modifying an array passed by reference)
1 parent 304ac56 commit 7ccd594

File tree

3 files changed

+44
-7
lines changed

3 files changed

+44
-7
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ PHP NEWS
1111
(Laruence)
1212

1313
- Core:
14+
. Fixed bug #61730 (Segfault from array_walk modifying an array passed by
15+
reference). (Laruence)
1416
. Fixed missing bound check in iptcparse(). (chris at chiappa.net)
1517
. Fixed bug #61764 ('I' unpacks n as signed if n > 2^31-1 on LP64). (Gustavo)
1618
. Fixed bug #54197 ([PATH=] sections incompatibility with user_ini.filename

ext/standard/array.c

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1052,7 +1052,6 @@ static int php_array_walk(HashTable *target_hash, zval *userdata, int recursive
10521052
char *string_key;
10531053
uint string_key_len;
10541054
ulong num_key;
1055-
HashPosition pos;
10561055

10571056
/* Set up known arguments */
10581057
args[1] = &key;
@@ -1061,15 +1060,14 @@ static int php_array_walk(HashTable *target_hash, zval *userdata, int recursive
10611060
Z_ADDREF_P(userdata);
10621061
}
10631062

1064-
zend_hash_internal_pointer_reset_ex(target_hash, &pos);
1065-
10661063
BG(array_walk_fci).retval_ptr_ptr = &retval_ptr;
10671064
BG(array_walk_fci).param_count = userdata ? 3 : 2;
10681065
BG(array_walk_fci).params = args;
10691066
BG(array_walk_fci).no_separation = 0;
1070-
1067+
10711068
/* Iterate through hash */
1072-
while (!EG(exception) && zend_hash_get_current_data_ex(target_hash, (void **)&args[0], &pos) == SUCCESS) {
1069+
zend_hash_internal_pointer_reset(target_hash);
1070+
while (!EG(exception) && zend_hash_get_current_data(target_hash, (void **)&args[0]) == SUCCESS) {
10731071
if (recursive && Z_TYPE_PP(args[0]) == IS_ARRAY) {
10741072
HashTable *thash;
10751073
zend_fcall_info orig_array_walk_fci;
@@ -1101,7 +1099,7 @@ static int php_array_walk(HashTable *target_hash, zval *userdata, int recursive
11011099
MAKE_STD_ZVAL(key);
11021100

11031101
/* Set up the key */
1104-
switch (zend_hash_get_current_key_ex(target_hash, &string_key, &string_key_len, &num_key, 0, &pos)) {
1102+
switch (zend_hash_get_current_key_ex(target_hash, &string_key, &string_key_len, &num_key, 0, NULL)) {
11051103
case HASH_KEY_IS_LONG:
11061104
Z_TYPE_P(key) = IS_LONG;
11071105
Z_LVAL_P(key) = num_key;
@@ -1129,7 +1127,7 @@ static int php_array_walk(HashTable *target_hash, zval *userdata, int recursive
11291127
zval_ptr_dtor(&key);
11301128
key = NULL;
11311129
}
1132-
zend_hash_move_forward_ex(target_hash, &pos);
1130+
zend_hash_move_forward(target_hash);
11331131
}
11341132

11351133
if (userdata) {

ext/standard/tests/bug61730.phpt

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
--TEST--
2+
Bug #61730 (Segfault from array_walk modifying an array passed by reference)
3+
--FILE--
4+
<?php
5+
$myArray = array_fill(0, 10, 1);
6+
7+
array_walk(
8+
$myArray,
9+
function($value, $key) use ($myArray)
10+
{
11+
reset($myArray);
12+
}
13+
);
14+
15+
array_walk(
16+
$myArray,
17+
function($value, $key) use (&$myArray)
18+
{
19+
var_dump($key);
20+
unset($myArray[$key]);
21+
unset($myArray[$key+1]);
22+
unset($myArray[$key+2]);
23+
}
24+
);
25+
26+
27+
28+
print_r($myArray);
29+
--EXPECT--
30+
int(0)
31+
int(4)
32+
int(8)
33+
Array
34+
(
35+
[3] => 1
36+
[7] => 1
37+
)

0 commit comments

Comments
 (0)