Skip to content

Commit f1425af

Browse files
committed
Avoid crash for reset/end/next/prev() on ffi classes
(And any PECLs returning `zend_empty_array` in the handler->get_properties overrides) Closes GH-9697 This is similar to the fix used in d9651a9 for array_walk. This should make it safer for php-src (and PECLs, long-term) to return the empty immutable array in `handler->get_properties` to avoid wasting memory. See #9697 (comment) The only possible internal iterator position for the empty array is at the end of the empty array (nInternalPointer=0). The `zend_hash*del*` helpers will always set nInternalPointer to 0 when an array becomes empty, regardless of previous insertions/deletions/updates to the array.
1 parent 2c8f2e9 commit f1425af

File tree

1 file changed

+16
-0
lines changed

1 file changed

+16
-0
lines changed

ext/standard/array.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,6 +1102,10 @@ PHP_FUNCTION(end)
11021102
Z_PARAM_ARRAY_OR_OBJECT_HT_EX(array, 0, 1)
11031103
ZEND_PARSE_PARAMETERS_END();
11041104

1105+
if (zend_hash_num_elements(array) == 0) {
1106+
/* array->nInternalPointer is already 0 if the array is empty, even after removing elements */
1107+
RETURN_FALSE;
1108+
}
11051109
zend_hash_internal_pointer_end(array);
11061110

11071111
if (USED_RET()) {
@@ -1128,6 +1132,10 @@ PHP_FUNCTION(prev)
11281132
Z_PARAM_ARRAY_OR_OBJECT_HT_EX(array, 0, 1)
11291133
ZEND_PARSE_PARAMETERS_END();
11301134

1135+
if (zend_hash_num_elements(array) == 0) {
1136+
/* array->nInternalPointer is already 0 if the array is empty, even after removing elements */
1137+
RETURN_FALSE;
1138+
}
11311139
zend_hash_move_backwards(array);
11321140

11331141
if (USED_RET()) {
@@ -1154,6 +1162,10 @@ PHP_FUNCTION(next)
11541162
Z_PARAM_ARRAY_OR_OBJECT_HT_EX(array, 0, 1)
11551163
ZEND_PARSE_PARAMETERS_END();
11561164

1165+
if (zend_hash_num_elements(array) == 0) {
1166+
/* array->nInternalPointer is already 0 if the array is empty, even after removing elements */
1167+
RETURN_FALSE;
1168+
}
11571169
zend_hash_move_forward(array);
11581170

11591171
if (USED_RET()) {
@@ -1180,6 +1192,10 @@ PHP_FUNCTION(reset)
11801192
Z_PARAM_ARRAY_OR_OBJECT_HT_EX(array, 0, 1)
11811193
ZEND_PARSE_PARAMETERS_END();
11821194

1195+
if (zend_hash_num_elements(array) == 0) {
1196+
/* array->nInternalPointer is already 0 if the array is empty, even after removing elements */
1197+
RETURN_FALSE;
1198+
}
11831199
zend_hash_internal_pointer_reset(array);
11841200

11851201
if (USED_RET()) {

0 commit comments

Comments
 (0)