diff --git a/ext/filter/logical_filters.c b/ext/filter/logical_filters.c index 45acf6d47541..1c46e3a9d141 100644 --- a/ext/filter/logical_filters.c +++ b/ext/filter/logical_filters.c @@ -35,7 +35,7 @@ #define FETCH_DOUBLE_OPTION(var_name, option_name) \ var_name = 0; \ var_name##_set = 0; \ - if (option_array) { \ + if (option_array && Z_TYPE_P(option_array) == IS_ARRAY) { \ if ((option_val = zend_hash_str_find(Z_ARRVAL_P(option_array), option_name, sizeof(option_name) - 1)) != NULL) { \ var_name = zval_get_double(option_val); \ var_name##_set = 1; \ @@ -47,7 +47,7 @@ #define FETCH_LONG_OPTION(var_name, option_name) \ var_name = 0; \ var_name##_set = 0; \ - if (option_array) { \ + if (option_array && Z_TYPE_P(option_array) == IS_ARRAY) { \ if ((option_val = zend_hash_str_find(Z_ARRVAL_P(option_array), option_name, sizeof(option_name) - 1)) != NULL) { \ var_name = zval_get_long(option_val); \ var_name##_set = 1; \ @@ -60,7 +60,7 @@ var_name = NULL; \ var_name##_set = 0; \ var_name##_len = 0; \ - if (option_array) { \ + if (option_array && Z_TYPE_P(option_array) == IS_ARRAY) { \ if ((option_val = zend_hash_str_find_deref(Z_ARRVAL_P(option_array), option_name, sizeof(option_name) - 1)) != NULL) { \ if (Z_TYPE_P(option_val) == IS_STRING) { \ var_name = Z_STRVAL_P(option_val); \ diff --git a/ext/filter/tests/gh24579.phpt b/ext/filter/tests/gh24579.phpt new file mode 100644 index 000000000000..fc4941084f53 --- /dev/null +++ b/ext/filter/tests/gh24579.phpt @@ -0,0 +1,27 @@ +--TEST-- +GH-24579: FILTER_VALIDATE_INT should not crash when __toString() mutates options array +--EXTENSIONS-- +filter +--FILE-- + 0]; +$args = ['options' => &$shared]; + +class Reenter +{ + public function __toString(): string + { + global $shared; + $shared = 'changed'; + return '1'; + } +} + +var_dump(filter_var(new Reenter(), FILTER_VALIDATE_INT, $args)); + +echo "No crash\n"; +?> +--EXPECT-- +int(1) +No crash