Skip to content

Commit f5c54fd

Browse files
committed
Fix access on NULL pointer in array_merge_recursive()
Closes GH-11303
1 parent 2f2fd06 commit f5c54fd

File tree

5 files changed

+40
-3
lines changed

5 files changed

+40
-3
lines changed

NEWS

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ PHP NEWS
22
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
33
?? ??? ????, PHP 8.1.21
44

5-
5+
- Standard:
6+
. Fix access on NULL pointer in array_merge_recursive(). (ilutov)
67

78
08 Jun 2023, PHP 8.1.20
89

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
--TEST--
2+
Access on NULL pointer in array_merge_recursive()
3+
--FILE--
4+
<?php
5+
try {
6+
array_merge_recursive(
7+
['' => [PHP_INT_MAX => null]],
8+
['' => [null]],
9+
);
10+
} catch (Throwable $e) {
11+
echo $e->getMessage(), "\n";
12+
}
13+
14+
try {
15+
array_merge_recursive(
16+
['foo' => [PHP_INT_MAX => null]],
17+
['foo' => str_repeat('a', 2)],
18+
);
19+
} catch (Throwable $e) {
20+
echo $e->getMessage(), "\n";
21+
}
22+
?>
23+
--EXPECT--
24+
Cannot add element to the array as the next element is already occupied
25+
Cannot add element to the array as the next element is already occupied

Zend/zend_execute.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2231,7 +2231,7 @@ static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_use_scalar_as_array(v
22312231
zend_throw_error(NULL, "Cannot use a scalar value as an array");
22322232
}
22332233

2234-
static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_cannot_add_element(void)
2234+
ZEND_API zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_cannot_add_element(void)
22352235
{
22362236
zend_throw_error(NULL, "Cannot add element to the array as the next element is already occupied");
22372237
}

Zend/zend_execute.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ ZEND_API ZEND_COLD void zend_wrong_string_offset_error(void);
7676
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_readonly_property_modification_error(zend_property_info *info);
7777
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_readonly_property_indirect_modification_error(zend_property_info *info);
7878

79+
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_cannot_add_element(void);
80+
7981
ZEND_API bool zend_verify_scalar_type_hint(uint32_t type_mask, zval *arg, bool strict, bool is_internal_arg);
8082
ZEND_API ZEND_COLD void zend_verify_arg_error(
8183
const zend_function *zf, const zend_arg_info *arg_info, uint32_t arg_num, zval *value);

ext/standard/array.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3595,7 +3595,12 @@ PHPAPI int php_array_merge_recursive(HashTable *dest, HashTable *src) /* {{{ */
35953595
}
35963596
} else {
35973597
Z_TRY_ADDREF_P(src_zval);
3598-
zend_hash_next_index_insert(Z_ARRVAL_P(dest_zval), src_zval);
3598+
zval *zv = zend_hash_next_index_insert(Z_ARRVAL_P(dest_zval), src_zval);
3599+
if (EXPECTED(!zv)) {
3600+
Z_TRY_DELREF_P(src_zval);
3601+
zend_cannot_add_element();
3602+
return 0;
3603+
}
35993604
}
36003605
zval_ptr_dtor(&tmp);
36013606
} else {
@@ -3604,6 +3609,10 @@ PHPAPI int php_array_merge_recursive(HashTable *dest, HashTable *src) /* {{{ */
36043609
}
36053610
} else {
36063611
zval *zv = zend_hash_next_index_insert(dest, src_entry);
3612+
if (UNEXPECTED(!zv)) {
3613+
zend_cannot_add_element();
3614+
return 0;
3615+
}
36073616
zval_add_ref(zv);
36083617
}
36093618
} ZEND_HASH_FOREACH_END();

0 commit comments

Comments
 (0)