Skip to content

ext/standard: validate mode in array_filter() #15647

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 18 additions & 7 deletions ext/standard/array.c
Original file line number Diff line number Diff line change
Expand Up @@ -6500,7 +6500,7 @@ PHP_FUNCTION(array_filter)
zval args[2];
zval retval;
bool have_callback = 0;
zend_long use_type = 0;
zend_long mode = ARRAY_FILTER_USE_VALUE;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please avoid the rename.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't mode a more relevant name than use_type that suggests boolean value?

This only touches internal variable, so I thought that shouldn't be a problem.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think use_type refers to "ARRAY_FILTER_USE_", so mode doesn't seem more descriptive.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mode is the literal name of the argument in the array_filter function.

https://www.php.net/manual/en/function.array-filter.php

For me, it doesn't make a big difference, rather than alignment, so I can change it tomorrow.

zend_string *string_key;
zend_fcall_info fci = empty_fcall_info;
zend_fcall_info_cache fci_cache = empty_fcall_info_cache;
Expand All @@ -6510,19 +6510,30 @@ PHP_FUNCTION(array_filter)
Z_PARAM_ARRAY(array)
Z_PARAM_OPTIONAL
Z_PARAM_FUNC_OR_NULL(fci, fci_cache)
Z_PARAM_LONG(use_type)
Z_PARAM_LONG(mode)
ZEND_PARSE_PARAMETERS_END();

switch (mode) {
case ARRAY_FILTER_USE_VALUE:
case ARRAY_FILTER_USE_BOTH:
case ARRAY_FILTER_USE_KEY:
break;
default:
zend_argument_value_error(3, "must be a valid mode");
RETURN_THROWS();
}

if (zend_hash_num_elements(Z_ARRVAL_P(array)) == 0) {
RETVAL_EMPTY_ARRAY();
return;
}

array_init(return_value);

if (ZEND_FCI_INITIALIZED(fci)) {
have_callback = 1;
fci.retval = &retval;
if (use_type == ARRAY_FILTER_USE_BOTH) {
if (mode == ARRAY_FILTER_USE_BOTH) {
fci.param_count = 2;
key = &args[1];
} else {
Expand All @@ -6533,15 +6544,15 @@ PHP_FUNCTION(array_filter)

ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(array), num_key, string_key, operand) {
if (have_callback) {
if (use_type) {
if (mode) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want to be explicit, you should use mode != ARRAY_FILTER_USE_VALUE, which should end up compiling to the same thing.

/* Set up the key */
if (!string_key) {
ZVAL_LONG(key, num_key);
} else {
ZVAL_STR_COPY(key, string_key);
}
}
if (use_type != ARRAY_FILTER_USE_KEY) {
if (mode != ARRAY_FILTER_USE_KEY) {
ZVAL_COPY(&args[0], operand);
}
fci.params = args;
Expand All @@ -6550,7 +6561,7 @@ PHP_FUNCTION(array_filter)
bool retval_true;

zval_ptr_dtor(&args[0]);
if (use_type == ARRAY_FILTER_USE_BOTH) {
if (mode == ARRAY_FILTER_USE_BOTH) {
zval_ptr_dtor(&args[1]);
}
retval_true = zend_is_true(&retval);
Expand All @@ -6560,7 +6571,7 @@ PHP_FUNCTION(array_filter)
}
} else {
zval_ptr_dtor(&args[0]);
if (use_type == ARRAY_FILTER_USE_BOTH) {
if (mode == ARRAY_FILTER_USE_BOTH) {
zval_ptr_dtor(&args[1]);
}
return;
Expand Down
1 change: 1 addition & 0 deletions ext/standard/php_array.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ PHPAPI bool php_array_pick_keys(php_random_algo_with_state engine, zval *input,
#define PHP_COUNT_NORMAL 0
#define PHP_COUNT_RECURSIVE 1

#define ARRAY_FILTER_USE_VALUE 0
#define ARRAY_FILTER_USE_BOTH 1
#define ARRAY_FILTER_USE_KEY 2

Expand Down
16 changes: 16 additions & 0 deletions ext/standard/tests/array/array_filter_invalid_mode.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
--TEST--
Test array_filter() function : usage variations - mode exception
--FILE--
<?php

try {
var_dump(array_filter([], mode: 999));
} catch (Throwable $e) {
echo $e::class . ': '.$e->getMessage(), "\n";
}

echo "Done"
?>
--EXPECT--
ValueError: array_filter(): Argument #3 ($mode) must be a valid mode
Done
Loading