From ca79b102894d0bbbb2f595d01cd50c725c3d1634 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 23 Nov 2024 15:28:58 +0100 Subject: [PATCH 1/7] Fix GH-16905: Internal iterator functions can't handle UNDEF properties --- ext/standard/array.c | 75 +++++++++------------------ ext/standard/tests/array/gh16905.phpt | 36 +++++++++++++ 2 files changed, 61 insertions(+), 50 deletions(-) create mode 100644 ext/standard/tests/array/gh16905.phpt diff --git a/ext/standard/array.c b/ext/standard/array.c index d4e3742bb71f..d394b58ace99 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -1029,11 +1029,30 @@ static inline HashTable *get_ht_for_iap(zval *zv, bool separate) { return zobj->handlers->get_properties(zobj); } +static void ia_return_current(zval *return_value, HashTable *array) +{ + zval *entry; + + if ((entry = zend_hash_get_current_data(array)) == NULL) { + RETURN_FALSE; + } + + if (Z_TYPE_P(entry) == IS_INDIRECT) { + entry = Z_INDIRECT_P(entry); + } + + /* Possible with an uninitialized typed property */ + if (Z_TYPE_P(entry) == IS_UNDEF) { + RETURN_FALSE; + } + + RETURN_COPY_DEREF(entry); +} + /* {{{ Advances array argument's internal pointer to the last element and return it */ PHP_FUNCTION(end) { zval *array_zv; - zval *entry; ZEND_PARSE_PARAMETERS_START(1, 1) Z_PARAM_ARRAY_OR_OBJECT_EX(array_zv, 0, 1) @@ -1047,15 +1066,7 @@ PHP_FUNCTION(end) zend_hash_internal_pointer_end(array); if (USED_RET()) { - if ((entry = zend_hash_get_current_data(array)) == NULL) { - RETURN_FALSE; - } - - if (Z_TYPE_P(entry) == IS_INDIRECT) { - entry = Z_INDIRECT_P(entry); - } - - RETURN_COPY_DEREF(entry); + ia_return_current(return_value, array); } } /* }}} */ @@ -1064,7 +1075,6 @@ PHP_FUNCTION(end) PHP_FUNCTION(prev) { zval *array_zv; - zval *entry; ZEND_PARSE_PARAMETERS_START(1, 1) Z_PARAM_ARRAY_OR_OBJECT_EX(array_zv, 0, 1) @@ -1078,15 +1088,7 @@ PHP_FUNCTION(prev) zend_hash_move_backwards(array); if (USED_RET()) { - if ((entry = zend_hash_get_current_data(array)) == NULL) { - RETURN_FALSE; - } - - if (Z_TYPE_P(entry) == IS_INDIRECT) { - entry = Z_INDIRECT_P(entry); - } - - RETURN_COPY_DEREF(entry); + ia_return_current(return_value, array); } } /* }}} */ @@ -1095,7 +1097,6 @@ PHP_FUNCTION(prev) PHP_FUNCTION(next) { zval *array_zv; - zval *entry; ZEND_PARSE_PARAMETERS_START(1, 1) Z_PARAM_ARRAY_OR_OBJECT_EX(array_zv, 0, 1) @@ -1109,15 +1110,7 @@ PHP_FUNCTION(next) zend_hash_move_forward(array); if (USED_RET()) { - if ((entry = zend_hash_get_current_data(array)) == NULL) { - RETURN_FALSE; - } - - if (Z_TYPE_P(entry) == IS_INDIRECT) { - entry = Z_INDIRECT_P(entry); - } - - RETURN_COPY_DEREF(entry); + ia_return_current(return_value, array); } } /* }}} */ @@ -1126,7 +1119,6 @@ PHP_FUNCTION(next) PHP_FUNCTION(reset) { zval *array_zv; - zval *entry; ZEND_PARSE_PARAMETERS_START(1, 1) Z_PARAM_ARRAY_OR_OBJECT_EX(array_zv, 0, 1) @@ -1140,15 +1132,7 @@ PHP_FUNCTION(reset) zend_hash_internal_pointer_reset(array); if (USED_RET()) { - if ((entry = zend_hash_get_current_data(array)) == NULL) { - RETURN_FALSE; - } - - if (Z_TYPE_P(entry) == IS_INDIRECT) { - entry = Z_INDIRECT_P(entry); - } - - RETURN_COPY_DEREF(entry); + ia_return_current(return_value, array); } } /* }}} */ @@ -1157,22 +1141,13 @@ PHP_FUNCTION(reset) PHP_FUNCTION(current) { zval *array_zv; - zval *entry; ZEND_PARSE_PARAMETERS_START(1, 1) Z_PARAM_ARRAY_OR_OBJECT(array_zv) ZEND_PARSE_PARAMETERS_END(); HashTable *array = get_ht_for_iap(array_zv, /* separate */ false); - if ((entry = zend_hash_get_current_data(array)) == NULL) { - RETURN_FALSE; - } - - if (Z_TYPE_P(entry) == IS_INDIRECT) { - entry = Z_INDIRECT_P(entry); - } - - RETURN_COPY_DEREF(entry); + ia_return_current(return_value, array); } /* }}} */ diff --git a/ext/standard/tests/array/gh16905.phpt b/ext/standard/tests/array/gh16905.phpt new file mode 100644 index 000000000000..8a76d1f72cb5 --- /dev/null +++ b/ext/standard/tests/array/gh16905.phpt @@ -0,0 +1,36 @@ +--TEST-- +GH-16905 (Internal iterator functions can't handle UNDEF properties) +--FILE-- + +--EXPECTF-- +Deprecated: reset(): Calling reset() on an object is deprecated in %s on line %d +bool(false) + +Deprecated: current(): Calling current() on an object is deprecated in %s on line %d +bool(false) + +Deprecated: end(): Calling end() on an object is deprecated in %s on line %d +bool(false) + +Deprecated: next(): Calling next() on an object is deprecated in %s on line %d +bool(false) + +Deprecated: prev(): Calling prev() on an object is deprecated in %s on line %d +bool(false) + +Deprecated: key(): Calling key() on an object is deprecated in %s on line %d +NULL From b3cc8a81b21f25ce9c0b9023f6839f18aae61367 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 23 Nov 2024 16:01:27 +0100 Subject: [PATCH 2/7] Use ZVAL_DEINDIRECT --- ext/standard/array.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ext/standard/array.c b/ext/standard/array.c index d394b58ace99..393e4f309000 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -1037,9 +1037,7 @@ static void ia_return_current(zval *return_value, HashTable *array) RETURN_FALSE; } - if (Z_TYPE_P(entry) == IS_INDIRECT) { - entry = Z_INDIRECT_P(entry); - } + ZVAL_DEINDIRECT(entry); /* Possible with an uninitialized typed property */ if (Z_TYPE_P(entry) == IS_UNDEF) { From 393199cb6dae23e224a1a6f290c77267c43c91b3 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 23 Nov 2024 16:08:46 +0100 Subject: [PATCH 3/7] Follow foreach behaviour --- ext/standard/array.c | 38 +++++++++++++++-------- ext/standard/tests/array/gh16905.phpt | 43 ++++++++++++++++++++++----- 2 files changed, 60 insertions(+), 21 deletions(-) diff --git a/ext/standard/array.c b/ext/standard/array.c index 393e4f309000..07d7d802ea52 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -1029,19 +1029,31 @@ static inline HashTable *get_ht_for_iap(zval *zv, bool separate) { return zobj->handlers->get_properties(zobj); } -static void ia_return_current(zval *return_value, HashTable *array) +static void ia_return_current(zval *return_value, HashTable *array, bool forward_direction) { zval *entry; - if ((entry = zend_hash_get_current_data(array)) == NULL) { - RETURN_FALSE; - } + while (true) { + if ((entry = zend_hash_get_current_data(array)) == NULL) { + RETURN_FALSE; + } - ZVAL_DEINDIRECT(entry); + ZVAL_DEINDIRECT(entry); - /* Possible with an uninitialized typed property */ - if (Z_TYPE_P(entry) == IS_UNDEF) { - RETURN_FALSE; + /* Possible with an uninitialized typed property */ + if (UNEXPECTED(Z_TYPE_P(entry) == IS_UNDEF)) { + zend_result result; + if (forward_direction) { + result = zend_hash_move_forward(array); + } else { + result = zend_hash_move_backwards(array); + } + if (result != SUCCESS) { + RETURN_FALSE; + } + } else { + break; + } } RETURN_COPY_DEREF(entry); @@ -1064,7 +1076,7 @@ PHP_FUNCTION(end) zend_hash_internal_pointer_end(array); if (USED_RET()) { - ia_return_current(return_value, array); + ia_return_current(return_value, array, false); } } /* }}} */ @@ -1086,7 +1098,7 @@ PHP_FUNCTION(prev) zend_hash_move_backwards(array); if (USED_RET()) { - ia_return_current(return_value, array); + ia_return_current(return_value, array, false); } } /* }}} */ @@ -1108,7 +1120,7 @@ PHP_FUNCTION(next) zend_hash_move_forward(array); if (USED_RET()) { - ia_return_current(return_value, array); + ia_return_current(return_value, array, true); } } /* }}} */ @@ -1130,7 +1142,7 @@ PHP_FUNCTION(reset) zend_hash_internal_pointer_reset(array); if (USED_RET()) { - ia_return_current(return_value, array); + ia_return_current(return_value, array, true); } } /* }}} */ @@ -1145,7 +1157,7 @@ PHP_FUNCTION(current) ZEND_PARSE_PARAMETERS_END(); HashTable *array = get_ht_for_iap(array_zv, /* separate */ false); - ia_return_current(return_value, array); + ia_return_current(return_value, array, true); } /* }}} */ diff --git a/ext/standard/tests/array/gh16905.phpt b/ext/standard/tests/array/gh16905.phpt index 8a76d1f72cb5..d25819216f87 100644 --- a/ext/standard/tests/array/gh16905.phpt +++ b/ext/standard/tests/array/gh16905.phpt @@ -3,34 +3,61 @@ GH-16905 (Internal iterator functions can't handle UNDEF properties) --FILE-- b = 1; +$x->c = 2; + var_dump(reset($x)); var_dump(current($x)); var_dump(end($x)); + +var_dump(reset($x)); var_dump(next($x)); + +var_dump(end($x)); var_dump(prev($x)); + var_dump(value: key($x)); +$x = new TestAllUndef; +var_dump(current($x)); + ?> --EXPECTF-- Deprecated: reset(): Calling reset() on an object is deprecated in %s on line %d -bool(false) +int(1) Deprecated: current(): Calling current() on an object is deprecated in %s on line %d -bool(false) +int(1) Deprecated: end(): Calling end() on an object is deprecated in %s on line %d -bool(false) +int(2) + +Deprecated: reset(): Calling reset() on an object is deprecated in %s on line %d +int(1) Deprecated: next(): Calling next() on an object is deprecated in %s on line %d -bool(false) +int(2) + +Deprecated: end(): Calling end() on an object is deprecated in %s on line %d +int(2) Deprecated: prev(): Calling prev() on an object is deprecated in %s on line %d -bool(false) +int(1) Deprecated: key(): Calling key() on an object is deprecated in %s on line %d -NULL +string(1) "b" + +Deprecated: current(): Calling current() on an object is deprecated in %s on line %d +bool(false) From 9a18fc7432c1e765c7741005ea30d9ced0cdf42a Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 24 Nov 2024 15:36:35 +0100 Subject: [PATCH 4/7] Throw in key() and current() when internal iterator points to undef element --- ext/standard/array.c | 40 +++++++++++++++++++++------ ext/standard/tests/array/gh16905.phpt | 23 ++++++++++++++- 2 files changed, 54 insertions(+), 9 deletions(-) diff --git a/ext/standard/array.c b/ext/standard/array.c index 07d7d802ea52..6757e9c84ba9 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -1029,7 +1029,18 @@ static inline HashTable *get_ht_for_iap(zval *zv, bool separate) { return zobj->handlers->get_properties(zobj); } -static void ia_return_current(zval *return_value, HashTable *array, bool forward_direction) +enum ia_undef_strategy { + IA_MOVE_FORWARD, + IA_MOVE_BACKWARD, + IA_THROW, +}; + +static ZEND_COLD void ia_throw_undef_error(void) +{ + zend_throw_error(NULL, "Internal iterator points to an uninitialized property"); +} + +static void ia_return_current(zval *return_value, HashTable *array, enum ia_undef_strategy undef_strategy) { zval *entry; @@ -1043,10 +1054,13 @@ static void ia_return_current(zval *return_value, HashTable *array, bool forward /* Possible with an uninitialized typed property */ if (UNEXPECTED(Z_TYPE_P(entry) == IS_UNDEF)) { zend_result result; - if (forward_direction) { + if (undef_strategy == IA_MOVE_FORWARD) { result = zend_hash_move_forward(array); - } else { + } else if (undef_strategy == IA_MOVE_BACKWARD) { result = zend_hash_move_backwards(array); + } else { + ia_throw_undef_error(); + return; } if (result != SUCCESS) { RETURN_FALSE; @@ -1076,7 +1090,7 @@ PHP_FUNCTION(end) zend_hash_internal_pointer_end(array); if (USED_RET()) { - ia_return_current(return_value, array, false); + ia_return_current(return_value, array, IA_MOVE_BACKWARD); } } /* }}} */ @@ -1098,7 +1112,7 @@ PHP_FUNCTION(prev) zend_hash_move_backwards(array); if (USED_RET()) { - ia_return_current(return_value, array, false); + ia_return_current(return_value, array, IA_MOVE_BACKWARD); } } /* }}} */ @@ -1120,7 +1134,7 @@ PHP_FUNCTION(next) zend_hash_move_forward(array); if (USED_RET()) { - ia_return_current(return_value, array, true); + ia_return_current(return_value, array, IA_MOVE_FORWARD); } } /* }}} */ @@ -1142,7 +1156,7 @@ PHP_FUNCTION(reset) zend_hash_internal_pointer_reset(array); if (USED_RET()) { - ia_return_current(return_value, array, true); + ia_return_current(return_value, array, IA_MOVE_FORWARD); } } /* }}} */ @@ -1157,7 +1171,7 @@ PHP_FUNCTION(current) ZEND_PARSE_PARAMETERS_END(); HashTable *array = get_ht_for_iap(array_zv, /* separate */ false); - ia_return_current(return_value, array, true); + ia_return_current(return_value, array, IA_THROW); } /* }}} */ @@ -1171,6 +1185,16 @@ PHP_FUNCTION(key) ZEND_PARSE_PARAMETERS_END(); HashTable *array = get_ht_for_iap(array_zv, /* separate */ false); + if (Z_TYPE_P(array_zv) == IS_OBJECT) { + zval *data = zend_hash_get_current_data(array); + if (data) { + ZVAL_DEINDIRECT(data); + if (Z_ISUNDEF_P(data)) { + ia_throw_undef_error(); + RETURN_THROWS(); + } + } + } zend_hash_get_current_key_zval(array, return_value); } /* }}} */ diff --git a/ext/standard/tests/array/gh16905.phpt b/ext/standard/tests/array/gh16905.phpt index d25819216f87..497b6c327a1d 100644 --- a/ext/standard/tests/array/gh16905.phpt +++ b/ext/standard/tests/array/gh16905.phpt @@ -31,7 +31,19 @@ var_dump(prev($x)); var_dump(value: key($x)); $x = new TestAllUndef; +try { + var_dump(current($x)); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +try { + var_dump(key($x)); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +$x->a = 1; var_dump(current($x)); +var_dump(key($x)); ?> --EXPECTF-- @@ -60,4 +72,13 @@ Deprecated: key(): Calling key() on an object is deprecated in %s on line %d string(1) "b" Deprecated: current(): Calling current() on an object is deprecated in %s on line %d -bool(false) +Internal iterator points to an uninitialized property + +Deprecated: key(): Calling key() on an object is deprecated in %s on line %d +Internal iterator points to an uninitialized property + +Deprecated: current(): Calling current() on an object is deprecated in %s on line %d +int(1) + +Deprecated: key(): Calling key() on an object is deprecated in %s on line %d +string(1) "a" From 031321a2588cb7b4fa205479da4361dbaf59452f Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 24 Nov 2024 19:32:20 +0100 Subject: [PATCH 5/7] Rename enum --- ext/standard/array.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/standard/array.c b/ext/standard/array.c index 6757e9c84ba9..a6c45c85a065 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -1029,7 +1029,7 @@ static inline HashTable *get_ht_for_iap(zval *zv, bool separate) { return zobj->handlers->get_properties(zobj); } -enum ia_undef_strategy { +enum php_array_iter_undef_strategy { IA_MOVE_FORWARD, IA_MOVE_BACKWARD, IA_THROW, @@ -1040,7 +1040,7 @@ static ZEND_COLD void ia_throw_undef_error(void) zend_throw_error(NULL, "Internal iterator points to an uninitialized property"); } -static void ia_return_current(zval *return_value, HashTable *array, enum ia_undef_strategy undef_strategy) +static void ia_return_current(zval *return_value, HashTable *array, enum php_array_iter_undef_strategy undef_strategy) { zval *entry; From 45428991fb6149378cdae1195279cd457bdc3854 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 24 Nov 2024 20:01:06 +0100 Subject: [PATCH 6/7] Rename more --- ext/standard/array.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/ext/standard/array.c b/ext/standard/array.c index a6c45c85a065..a6ae179610d8 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -1035,12 +1035,12 @@ enum php_array_iter_undef_strategy { IA_THROW, }; -static ZEND_COLD void ia_throw_undef_error(void) +static ZEND_COLD void php_array_iter_throw_undef_error(void) { zend_throw_error(NULL, "Internal iterator points to an uninitialized property"); } -static void ia_return_current(zval *return_value, HashTable *array, enum php_array_iter_undef_strategy undef_strategy) +static void php_array_iter_return_current(zval *return_value, HashTable *array, enum php_array_iter_undef_strategy undef_strategy) { zval *entry; @@ -1059,7 +1059,7 @@ static void ia_return_current(zval *return_value, HashTable *array, enum php_arr } else if (undef_strategy == IA_MOVE_BACKWARD) { result = zend_hash_move_backwards(array); } else { - ia_throw_undef_error(); + php_array_iter_throw_undef_error(); return; } if (result != SUCCESS) { @@ -1090,7 +1090,7 @@ PHP_FUNCTION(end) zend_hash_internal_pointer_end(array); if (USED_RET()) { - ia_return_current(return_value, array, IA_MOVE_BACKWARD); + php_array_iter_return_current(return_value, array, IA_MOVE_BACKWARD); } } /* }}} */ @@ -1112,7 +1112,7 @@ PHP_FUNCTION(prev) zend_hash_move_backwards(array); if (USED_RET()) { - ia_return_current(return_value, array, IA_MOVE_BACKWARD); + php_array_iter_return_current(return_value, array, IA_MOVE_BACKWARD); } } /* }}} */ @@ -1134,7 +1134,7 @@ PHP_FUNCTION(next) zend_hash_move_forward(array); if (USED_RET()) { - ia_return_current(return_value, array, IA_MOVE_FORWARD); + php_array_iter_return_current(return_value, array, IA_MOVE_FORWARD); } } /* }}} */ @@ -1156,7 +1156,7 @@ PHP_FUNCTION(reset) zend_hash_internal_pointer_reset(array); if (USED_RET()) { - ia_return_current(return_value, array, IA_MOVE_FORWARD); + php_array_iter_return_current(return_value, array, IA_MOVE_FORWARD); } } /* }}} */ @@ -1171,7 +1171,7 @@ PHP_FUNCTION(current) ZEND_PARSE_PARAMETERS_END(); HashTable *array = get_ht_for_iap(array_zv, /* separate */ false); - ia_return_current(return_value, array, IA_THROW); + php_array_iter_return_current(return_value, array, IA_THROW); } /* }}} */ @@ -1190,7 +1190,7 @@ PHP_FUNCTION(key) if (data) { ZVAL_DEINDIRECT(data); if (Z_ISUNDEF_P(data)) { - ia_throw_undef_error(); + php_array_iter_throw_undef_error(); RETURN_THROWS(); } } From 165b07aba5b85f82b95b4c128e1e16d7b363350f Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Mon, 25 Nov 2024 21:42:53 +0100 Subject: [PATCH 7/7] Change strategy again --- ext/standard/array.c | 59 +++++++++++---------------- ext/standard/tests/array/gh16905.phpt | 36 +++++++++------- 2 files changed, 46 insertions(+), 49 deletions(-) diff --git a/ext/standard/array.c b/ext/standard/array.c index a6ae179610d8..a1a929340848 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -1029,24 +1029,13 @@ static inline HashTable *get_ht_for_iap(zval *zv, bool separate) { return zobj->handlers->get_properties(zobj); } -enum php_array_iter_undef_strategy { - IA_MOVE_FORWARD, - IA_MOVE_BACKWARD, - IA_THROW, -}; - -static ZEND_COLD void php_array_iter_throw_undef_error(void) -{ - zend_throw_error(NULL, "Internal iterator points to an uninitialized property"); -} - -static void php_array_iter_return_current(zval *return_value, HashTable *array, enum php_array_iter_undef_strategy undef_strategy) +static zval *php_array_iter_seek_current(HashTable *array, bool forward_direction) { zval *entry; while (true) { if ((entry = zend_hash_get_current_data(array)) == NULL) { - RETURN_FALSE; + return NULL; } ZVAL_DEINDIRECT(entry); @@ -1054,23 +1043,30 @@ static void php_array_iter_return_current(zval *return_value, HashTable *array, /* Possible with an uninitialized typed property */ if (UNEXPECTED(Z_TYPE_P(entry) == IS_UNDEF)) { zend_result result; - if (undef_strategy == IA_MOVE_FORWARD) { + if (forward_direction) { result = zend_hash_move_forward(array); - } else if (undef_strategy == IA_MOVE_BACKWARD) { - result = zend_hash_move_backwards(array); } else { - php_array_iter_throw_undef_error(); - return; + result = zend_hash_move_backwards(array); } if (result != SUCCESS) { - RETURN_FALSE; + return NULL; } } else { break; } } - RETURN_COPY_DEREF(entry); + return entry; +} + +static void php_array_iter_return_current(zval *return_value, HashTable *array, bool forward_direction) +{ + zval *entry = php_array_iter_seek_current(array, forward_direction); + if (EXPECTED(entry)) { + RETURN_COPY_DEREF(entry); + } else { + RETURN_FALSE; + } } /* {{{ Advances array argument's internal pointer to the last element and return it */ @@ -1090,7 +1086,7 @@ PHP_FUNCTION(end) zend_hash_internal_pointer_end(array); if (USED_RET()) { - php_array_iter_return_current(return_value, array, IA_MOVE_BACKWARD); + php_array_iter_return_current(return_value, array, false); } } /* }}} */ @@ -1112,7 +1108,7 @@ PHP_FUNCTION(prev) zend_hash_move_backwards(array); if (USED_RET()) { - php_array_iter_return_current(return_value, array, IA_MOVE_BACKWARD); + php_array_iter_return_current(return_value, array, false); } } /* }}} */ @@ -1134,7 +1130,7 @@ PHP_FUNCTION(next) zend_hash_move_forward(array); if (USED_RET()) { - php_array_iter_return_current(return_value, array, IA_MOVE_FORWARD); + php_array_iter_return_current(return_value, array, true); } } /* }}} */ @@ -1156,7 +1152,7 @@ PHP_FUNCTION(reset) zend_hash_internal_pointer_reset(array); if (USED_RET()) { - php_array_iter_return_current(return_value, array, IA_MOVE_FORWARD); + php_array_iter_return_current(return_value, array, true); } } /* }}} */ @@ -1171,7 +1167,7 @@ PHP_FUNCTION(current) ZEND_PARSE_PARAMETERS_END(); HashTable *array = get_ht_for_iap(array_zv, /* separate */ false); - php_array_iter_return_current(return_value, array, IA_THROW); + php_array_iter_return_current(return_value, array, true); } /* }}} */ @@ -1185,17 +1181,10 @@ PHP_FUNCTION(key) ZEND_PARSE_PARAMETERS_END(); HashTable *array = get_ht_for_iap(array_zv, /* separate */ false); - if (Z_TYPE_P(array_zv) == IS_OBJECT) { - zval *data = zend_hash_get_current_data(array); - if (data) { - ZVAL_DEINDIRECT(data); - if (Z_ISUNDEF_P(data)) { - php_array_iter_throw_undef_error(); - RETURN_THROWS(); - } - } + zval *entry = php_array_iter_seek_current(array, true); + if (EXPECTED(entry)) { + zend_hash_get_current_key_zval(array, return_value); } - zend_hash_get_current_key_zval(array, return_value); } /* }}} */ diff --git a/ext/standard/tests/array/gh16905.phpt b/ext/standard/tests/array/gh16905.phpt index 497b6c327a1d..89d11575789e 100644 --- a/ext/standard/tests/array/gh16905.phpt +++ b/ext/standard/tests/array/gh16905.phpt @@ -28,22 +28,19 @@ var_dump(next($x)); var_dump(end($x)); var_dump(prev($x)); -var_dump(value: key($x)); +var_dump(key($x)); +var_dump(current($x)); $x = new TestAllUndef; -try { - var_dump(current($x)); -} catch (Error $e) { - echo $e->getMessage(), "\n"; -} -try { - var_dump(key($x)); -} catch (Error $e) { - echo $e->getMessage(), "\n"; -} +var_dump(key($x)); +var_dump(current($x)); + $x->a = 1; +var_dump(key($x)); var_dump(current($x)); +reset($x); var_dump(key($x)); +var_dump(current($x)); ?> --EXPECTF-- @@ -72,13 +69,24 @@ Deprecated: key(): Calling key() on an object is deprecated in %s on line %d string(1) "b" Deprecated: current(): Calling current() on an object is deprecated in %s on line %d -Internal iterator points to an uninitialized property +int(1) + +Deprecated: key(): Calling key() on an object is deprecated in %s on line %d +NULL + +Deprecated: current(): Calling current() on an object is deprecated in %s on line %d +bool(false) Deprecated: key(): Calling key() on an object is deprecated in %s on line %d -Internal iterator points to an uninitialized property +NULL Deprecated: current(): Calling current() on an object is deprecated in %s on line %d -int(1) +bool(false) + +Deprecated: reset(): Calling reset() on an object is deprecated in %s on line %d Deprecated: key(): Calling key() on an object is deprecated in %s on line %d string(1) "a" + +Deprecated: current(): Calling current() on an object is deprecated in %s on line %d +int(1)