Skip to content

Commit ca79b10

Browse files
committed
Fix GH-16905: Internal iterator functions can't handle UNDEF properties
1 parent ff3b4ec commit ca79b10

File tree

2 files changed

+61
-50
lines changed

2 files changed

+61
-50
lines changed

ext/standard/array.c

Lines changed: 25 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,11 +1029,30 @@ static inline HashTable *get_ht_for_iap(zval *zv, bool separate) {
10291029
return zobj->handlers->get_properties(zobj);
10301030
}
10311031

1032+
static void ia_return_current(zval *return_value, HashTable *array)
1033+
{
1034+
zval *entry;
1035+
1036+
if ((entry = zend_hash_get_current_data(array)) == NULL) {
1037+
RETURN_FALSE;
1038+
}
1039+
1040+
if (Z_TYPE_P(entry) == IS_INDIRECT) {
1041+
entry = Z_INDIRECT_P(entry);
1042+
}
1043+
1044+
/* Possible with an uninitialized typed property */
1045+
if (Z_TYPE_P(entry) == IS_UNDEF) {
1046+
RETURN_FALSE;
1047+
}
1048+
1049+
RETURN_COPY_DEREF(entry);
1050+
}
1051+
10321052
/* {{{ Advances array argument's internal pointer to the last element and return it */
10331053
PHP_FUNCTION(end)
10341054
{
10351055
zval *array_zv;
1036-
zval *entry;
10371056

10381057
ZEND_PARSE_PARAMETERS_START(1, 1)
10391058
Z_PARAM_ARRAY_OR_OBJECT_EX(array_zv, 0, 1)
@@ -1047,15 +1066,7 @@ PHP_FUNCTION(end)
10471066
zend_hash_internal_pointer_end(array);
10481067

10491068
if (USED_RET()) {
1050-
if ((entry = zend_hash_get_current_data(array)) == NULL) {
1051-
RETURN_FALSE;
1052-
}
1053-
1054-
if (Z_TYPE_P(entry) == IS_INDIRECT) {
1055-
entry = Z_INDIRECT_P(entry);
1056-
}
1057-
1058-
RETURN_COPY_DEREF(entry);
1069+
ia_return_current(return_value, array);
10591070
}
10601071
}
10611072
/* }}} */
@@ -1064,7 +1075,6 @@ PHP_FUNCTION(end)
10641075
PHP_FUNCTION(prev)
10651076
{
10661077
zval *array_zv;
1067-
zval *entry;
10681078

10691079
ZEND_PARSE_PARAMETERS_START(1, 1)
10701080
Z_PARAM_ARRAY_OR_OBJECT_EX(array_zv, 0, 1)
@@ -1078,15 +1088,7 @@ PHP_FUNCTION(prev)
10781088
zend_hash_move_backwards(array);
10791089

10801090
if (USED_RET()) {
1081-
if ((entry = zend_hash_get_current_data(array)) == NULL) {
1082-
RETURN_FALSE;
1083-
}
1084-
1085-
if (Z_TYPE_P(entry) == IS_INDIRECT) {
1086-
entry = Z_INDIRECT_P(entry);
1087-
}
1088-
1089-
RETURN_COPY_DEREF(entry);
1091+
ia_return_current(return_value, array);
10901092
}
10911093
}
10921094
/* }}} */
@@ -1095,7 +1097,6 @@ PHP_FUNCTION(prev)
10951097
PHP_FUNCTION(next)
10961098
{
10971099
zval *array_zv;
1098-
zval *entry;
10991100

11001101
ZEND_PARSE_PARAMETERS_START(1, 1)
11011102
Z_PARAM_ARRAY_OR_OBJECT_EX(array_zv, 0, 1)
@@ -1109,15 +1110,7 @@ PHP_FUNCTION(next)
11091110
zend_hash_move_forward(array);
11101111

11111112
if (USED_RET()) {
1112-
if ((entry = zend_hash_get_current_data(array)) == NULL) {
1113-
RETURN_FALSE;
1114-
}
1115-
1116-
if (Z_TYPE_P(entry) == IS_INDIRECT) {
1117-
entry = Z_INDIRECT_P(entry);
1118-
}
1119-
1120-
RETURN_COPY_DEREF(entry);
1113+
ia_return_current(return_value, array);
11211114
}
11221115
}
11231116
/* }}} */
@@ -1126,7 +1119,6 @@ PHP_FUNCTION(next)
11261119
PHP_FUNCTION(reset)
11271120
{
11281121
zval *array_zv;
1129-
zval *entry;
11301122

11311123
ZEND_PARSE_PARAMETERS_START(1, 1)
11321124
Z_PARAM_ARRAY_OR_OBJECT_EX(array_zv, 0, 1)
@@ -1140,15 +1132,7 @@ PHP_FUNCTION(reset)
11401132
zend_hash_internal_pointer_reset(array);
11411133

11421134
if (USED_RET()) {
1143-
if ((entry = zend_hash_get_current_data(array)) == NULL) {
1144-
RETURN_FALSE;
1145-
}
1146-
1147-
if (Z_TYPE_P(entry) == IS_INDIRECT) {
1148-
entry = Z_INDIRECT_P(entry);
1149-
}
1150-
1151-
RETURN_COPY_DEREF(entry);
1135+
ia_return_current(return_value, array);
11521136
}
11531137
}
11541138
/* }}} */
@@ -1157,22 +1141,13 @@ PHP_FUNCTION(reset)
11571141
PHP_FUNCTION(current)
11581142
{
11591143
zval *array_zv;
1160-
zval *entry;
11611144

11621145
ZEND_PARSE_PARAMETERS_START(1, 1)
11631146
Z_PARAM_ARRAY_OR_OBJECT(array_zv)
11641147
ZEND_PARSE_PARAMETERS_END();
11651148

11661149
HashTable *array = get_ht_for_iap(array_zv, /* separate */ false);
1167-
if ((entry = zend_hash_get_current_data(array)) == NULL) {
1168-
RETURN_FALSE;
1169-
}
1170-
1171-
if (Z_TYPE_P(entry) == IS_INDIRECT) {
1172-
entry = Z_INDIRECT_P(entry);
1173-
}
1174-
1175-
RETURN_COPY_DEREF(entry);
1150+
ia_return_current(return_value, array);
11761151
}
11771152
/* }}} */
11781153

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
--TEST--
2+
GH-16905 (Internal iterator functions can't handle UNDEF properties)
3+
--FILE--
4+
<?php
5+
6+
class X {
7+
public int $a;
8+
}
9+
10+
$x = new X;
11+
var_dump(reset($x));
12+
var_dump(current($x));
13+
var_dump(end($x));
14+
var_dump(next($x));
15+
var_dump(prev($x));
16+
var_dump(value: key($x));
17+
18+
?>
19+
--EXPECTF--
20+
Deprecated: reset(): Calling reset() on an object is deprecated in %s on line %d
21+
bool(false)
22+
23+
Deprecated: current(): Calling current() on an object is deprecated in %s on line %d
24+
bool(false)
25+
26+
Deprecated: end(): Calling end() on an object is deprecated in %s on line %d
27+
bool(false)
28+
29+
Deprecated: next(): Calling next() on an object is deprecated in %s on line %d
30+
bool(false)
31+
32+
Deprecated: prev(): Calling prev() on an object is deprecated in %s on line %d
33+
bool(false)
34+
35+
Deprecated: key(): Calling key() on an object is deprecated in %s on line %d
36+
NULL

0 commit comments

Comments
 (0)