mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
Merge branch 'PHP-8.4'
* PHP-8.4: Fix GH-16905: Internal iterator functions can't handle UNDEF properties
This commit is contained in:
commit
c10f5ce9c1
2 changed files with 141 additions and 51 deletions
|
@ -1024,11 +1024,50 @@ static inline HashTable *get_ht_for_iap(zval *zv, bool separate) {
|
||||||
return zobj->handlers->get_properties(zobj);
|
return zobj->handlers->get_properties(zobj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZVAL_DEINDIRECT(entry);
|
||||||
|
|
||||||
|
/* 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 NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 */
|
/* {{{ Advances array argument's internal pointer to the last element and return it */
|
||||||
PHP_FUNCTION(end)
|
PHP_FUNCTION(end)
|
||||||
{
|
{
|
||||||
zval *array_zv;
|
zval *array_zv;
|
||||||
zval *entry;
|
|
||||||
|
|
||||||
ZEND_PARSE_PARAMETERS_START(1, 1)
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
||||||
Z_PARAM_ARRAY_OR_OBJECT_EX(array_zv, 0, 1)
|
Z_PARAM_ARRAY_OR_OBJECT_EX(array_zv, 0, 1)
|
||||||
|
@ -1042,15 +1081,7 @@ PHP_FUNCTION(end)
|
||||||
zend_hash_internal_pointer_end(array);
|
zend_hash_internal_pointer_end(array);
|
||||||
|
|
||||||
if (USED_RET()) {
|
if (USED_RET()) {
|
||||||
if ((entry = zend_hash_get_current_data(array)) == NULL) {
|
php_array_iter_return_current(return_value, array, false);
|
||||||
RETURN_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Z_TYPE_P(entry) == IS_INDIRECT) {
|
|
||||||
entry = Z_INDIRECT_P(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
RETURN_COPY_DEREF(entry);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
@ -1059,7 +1090,6 @@ PHP_FUNCTION(end)
|
||||||
PHP_FUNCTION(prev)
|
PHP_FUNCTION(prev)
|
||||||
{
|
{
|
||||||
zval *array_zv;
|
zval *array_zv;
|
||||||
zval *entry;
|
|
||||||
|
|
||||||
ZEND_PARSE_PARAMETERS_START(1, 1)
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
||||||
Z_PARAM_ARRAY_OR_OBJECT_EX(array_zv, 0, 1)
|
Z_PARAM_ARRAY_OR_OBJECT_EX(array_zv, 0, 1)
|
||||||
|
@ -1073,15 +1103,7 @@ PHP_FUNCTION(prev)
|
||||||
zend_hash_move_backwards(array);
|
zend_hash_move_backwards(array);
|
||||||
|
|
||||||
if (USED_RET()) {
|
if (USED_RET()) {
|
||||||
if ((entry = zend_hash_get_current_data(array)) == NULL) {
|
php_array_iter_return_current(return_value, array, false);
|
||||||
RETURN_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Z_TYPE_P(entry) == IS_INDIRECT) {
|
|
||||||
entry = Z_INDIRECT_P(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
RETURN_COPY_DEREF(entry);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
@ -1090,7 +1112,6 @@ PHP_FUNCTION(prev)
|
||||||
PHP_FUNCTION(next)
|
PHP_FUNCTION(next)
|
||||||
{
|
{
|
||||||
zval *array_zv;
|
zval *array_zv;
|
||||||
zval *entry;
|
|
||||||
|
|
||||||
ZEND_PARSE_PARAMETERS_START(1, 1)
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
||||||
Z_PARAM_ARRAY_OR_OBJECT_EX(array_zv, 0, 1)
|
Z_PARAM_ARRAY_OR_OBJECT_EX(array_zv, 0, 1)
|
||||||
|
@ -1104,15 +1125,7 @@ PHP_FUNCTION(next)
|
||||||
zend_hash_move_forward(array);
|
zend_hash_move_forward(array);
|
||||||
|
|
||||||
if (USED_RET()) {
|
if (USED_RET()) {
|
||||||
if ((entry = zend_hash_get_current_data(array)) == NULL) {
|
php_array_iter_return_current(return_value, array, true);
|
||||||
RETURN_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Z_TYPE_P(entry) == IS_INDIRECT) {
|
|
||||||
entry = Z_INDIRECT_P(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
RETURN_COPY_DEREF(entry);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
@ -1121,7 +1134,6 @@ PHP_FUNCTION(next)
|
||||||
PHP_FUNCTION(reset)
|
PHP_FUNCTION(reset)
|
||||||
{
|
{
|
||||||
zval *array_zv;
|
zval *array_zv;
|
||||||
zval *entry;
|
|
||||||
|
|
||||||
ZEND_PARSE_PARAMETERS_START(1, 1)
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
||||||
Z_PARAM_ARRAY_OR_OBJECT_EX(array_zv, 0, 1)
|
Z_PARAM_ARRAY_OR_OBJECT_EX(array_zv, 0, 1)
|
||||||
|
@ -1135,15 +1147,7 @@ PHP_FUNCTION(reset)
|
||||||
zend_hash_internal_pointer_reset(array);
|
zend_hash_internal_pointer_reset(array);
|
||||||
|
|
||||||
if (USED_RET()) {
|
if (USED_RET()) {
|
||||||
if ((entry = zend_hash_get_current_data(array)) == NULL) {
|
php_array_iter_return_current(return_value, array, true);
|
||||||
RETURN_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Z_TYPE_P(entry) == IS_INDIRECT) {
|
|
||||||
entry = Z_INDIRECT_P(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
RETURN_COPY_DEREF(entry);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
@ -1152,22 +1156,13 @@ PHP_FUNCTION(reset)
|
||||||
PHP_FUNCTION(current)
|
PHP_FUNCTION(current)
|
||||||
{
|
{
|
||||||
zval *array_zv;
|
zval *array_zv;
|
||||||
zval *entry;
|
|
||||||
|
|
||||||
ZEND_PARSE_PARAMETERS_START(1, 1)
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
||||||
Z_PARAM_ARRAY_OR_OBJECT(array_zv)
|
Z_PARAM_ARRAY_OR_OBJECT(array_zv)
|
||||||
ZEND_PARSE_PARAMETERS_END();
|
ZEND_PARSE_PARAMETERS_END();
|
||||||
|
|
||||||
HashTable *array = get_ht_for_iap(array_zv, /* separate */ false);
|
HashTable *array = get_ht_for_iap(array_zv, /* separate */ false);
|
||||||
if ((entry = zend_hash_get_current_data(array)) == NULL) {
|
php_array_iter_return_current(return_value, array, true);
|
||||||
RETURN_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Z_TYPE_P(entry) == IS_INDIRECT) {
|
|
||||||
entry = Z_INDIRECT_P(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
RETURN_COPY_DEREF(entry);
|
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
@ -1181,7 +1176,10 @@ PHP_FUNCTION(key)
|
||||||
ZEND_PARSE_PARAMETERS_END();
|
ZEND_PARSE_PARAMETERS_END();
|
||||||
|
|
||||||
HashTable *array = get_ht_for_iap(array_zv, /* separate */ false);
|
HashTable *array = get_ht_for_iap(array_zv, /* separate */ false);
|
||||||
zend_hash_get_current_key_zval(array, return_value);
|
zval *entry = php_array_iter_seek_current(array, true);
|
||||||
|
if (EXPECTED(entry)) {
|
||||||
|
zend_hash_get_current_key_zval(array, return_value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
|
92
ext/standard/tests/array/gh16905.phpt
Normal file
92
ext/standard/tests/array/gh16905.phpt
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
--TEST--
|
||||||
|
GH-16905 (Internal iterator functions can't handle UNDEF properties)
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class TestSomeUndef {
|
||||||
|
public int $a;
|
||||||
|
public int $b;
|
||||||
|
public int $c;
|
||||||
|
public int $d;
|
||||||
|
}
|
||||||
|
|
||||||
|
class TestAllUndef {
|
||||||
|
public int $a;
|
||||||
|
}
|
||||||
|
|
||||||
|
$x = new TestSomeUndef;
|
||||||
|
$x->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(key($x));
|
||||||
|
var_dump(current($x));
|
||||||
|
|
||||||
|
$x = new TestAllUndef;
|
||||||
|
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--
|
||||||
|
Deprecated: reset(): Calling reset() on an object is deprecated in %s on line %d
|
||||||
|
int(1)
|
||||||
|
|
||||||
|
Deprecated: current(): Calling current() on an object is deprecated in %s on line %d
|
||||||
|
int(1)
|
||||||
|
|
||||||
|
Deprecated: end(): Calling end() on an object is deprecated in %s on line %d
|
||||||
|
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
|
||||||
|
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
|
||||||
|
int(1)
|
||||||
|
|
||||||
|
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
|
||||||
|
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
|
||||||
|
NULL
|
||||||
|
|
||||||
|
Deprecated: current(): Calling current() on an object is deprecated in %s on line %d
|
||||||
|
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)
|
Loading…
Add table
Add a link
Reference in a new issue