diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index b950330061920..5cb3e27bbb861 100644 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -1203,43 +1203,54 @@ PHP_METHOD(ArrayObject, count) RETURN_LONG(spl_array_object_count_elements_helper(intern)); } /* }}} */ -static void spl_array_method(INTERNAL_FUNCTION_PARAMETERS, char *fname, size_t fname_len, int use_arg) /* {{{ */ +enum spl_array_object_sort_methods { + SPL_NAT_SORT, + SPL_CALLBACK_SORT, + SPL_OPTIONAL_FLAG_SORT +}; + +static void spl_array_method(INTERNAL_FUNCTION_PARAMETERS, const char *fname, size_t fname_len, enum spl_array_object_sort_methods use_arg) /* {{{ */ { spl_array_object *intern = Z_SPLARRAY_P(ZEND_THIS); HashTable **ht_ptr = spl_array_get_hash_table_ptr(intern); HashTable *aht = *ht_ptr; - zval function_name, params[2], *arg = NULL; + zval params[2], *arg = NULL; - ZVAL_STRINGL(&function_name, fname, fname_len); + zend_function *fn = zend_hash_str_find_ptr(EG(function_table), fname, fname_len); + if (UNEXPECTED(fn == NULL)) { + zend_throw_error(NULL, "Cannot call method %s when function %s is disabled", fname, fname); + RETURN_THROWS(); + } ZVAL_NEW_EMPTY_REF(¶ms[0]); ZVAL_ARR(Z_REFVAL(params[0]), aht); GC_ADDREF(aht); - if (!use_arg) { + if (use_arg == SPL_NAT_SORT) { if (zend_parse_parameters_none() == FAILURE) { goto exit; } intern->nApplyCount++; - call_user_function(EG(function_table), NULL, &function_name, return_value, 1, params); + zend_call_known_function(fn, NULL, NULL, return_value, 1, params, NULL); intern->nApplyCount--; - } else if (use_arg == SPL_ARRAY_METHOD_SORT_FLAGS_ARG) { + } else if (use_arg == SPL_OPTIONAL_FLAG_SORT) { zend_long sort_flags = 0; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &sort_flags) == FAILURE) { goto exit; } ZVAL_LONG(¶ms[1], sort_flags); intern->nApplyCount++; - call_user_function(EG(function_table), NULL, &function_name, return_value, 2, params); + zend_call_known_function(fn, NULL, NULL, return_value, 2, params, NULL); intern->nApplyCount--; } else { + ZEND_ASSERT(use_arg == SPL_CALLBACK_SORT); if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &arg) == FAILURE) { goto exit; } ZVAL_COPY_VALUE(¶ms[1], arg); intern->nApplyCount++; - call_user_function(EG(function_table), NULL, &function_name, return_value, 2, params); + zend_call_known_function(fn, NULL, NULL, return_value, 2, params, NULL); intern->nApplyCount--; } @@ -1251,7 +1262,6 @@ static void spl_array_method(INTERNAL_FUNCTION_PARAMETERS, char *fname, size_t f *ht_ptr = Z_ARRVAL_P(ht_zv); ZVAL_NULL(ht_zv); zval_ptr_dtor(¶ms[0]); - zend_string_free(Z_STR(function_name)); } } /* }}} */ @@ -1261,23 +1271,23 @@ PHP_METHOD(cname, fname) \ spl_array_method(INTERNAL_FUNCTION_PARAM_PASSTHRU, #fname, sizeof(#fname)-1, use_arg); \ } -/* {{{ Sort the entries by values. */ -SPL_ARRAY_METHOD(ArrayObject, asort, SPL_ARRAY_METHOD_SORT_FLAGS_ARG) /* }}} */ +/* Sort the entries by values. */ +SPL_ARRAY_METHOD(ArrayObject, asort, SPL_OPTIONAL_FLAG_SORT) -/* {{{ Sort the entries by key. */ -SPL_ARRAY_METHOD(ArrayObject, ksort, SPL_ARRAY_METHOD_SORT_FLAGS_ARG) /* }}} */ +/* Sort the entries by key. */ +SPL_ARRAY_METHOD(ArrayObject, ksort, SPL_OPTIONAL_FLAG_SORT) -/* {{{ Sort the entries by values user defined function. */ -SPL_ARRAY_METHOD(ArrayObject, uasort, SPL_ARRAY_METHOD_CALLBACK_ARG) /* }}} */ +/* Sort the entries by values user defined function. */ +SPL_ARRAY_METHOD(ArrayObject, uasort, SPL_CALLBACK_SORT) -/* {{{ Sort the entries by key using user defined function. */ -SPL_ARRAY_METHOD(ArrayObject, uksort, SPL_ARRAY_METHOD_CALLBACK_ARG) /* }}} */ +/* Sort the entries by key using user defined function. */ +SPL_ARRAY_METHOD(ArrayObject, uksort, SPL_CALLBACK_SORT) -/* {{{ Sort the entries by values using "natural order" algorithm. */ -SPL_ARRAY_METHOD(ArrayObject, natsort, SPL_ARRAY_METHOD_NO_ARG) /* }}} */ +/* Sort the entries by values using "natural order" algorithm. */ +SPL_ARRAY_METHOD(ArrayObject, natsort, SPL_NAT_SORT) -/* {{{ Sort the entries by key using case insensitive "natural order" algorithm. */ -SPL_ARRAY_METHOD(ArrayObject, natcasesort, SPL_ARRAY_METHOD_NO_ARG) /* }}} */ +/* {{{ Sort the entries by key using case-insensitive "natural order" algorithm. */ +SPL_ARRAY_METHOD(ArrayObject, natcasesort, SPL_NAT_SORT) /* {{{ Serialize the object */ PHP_METHOD(ArrayObject, serialize) diff --git a/ext/spl/spl_array.h b/ext/spl/spl_array.h index f3577f4beeaad..86de7a955c5b2 100644 --- a/ext/spl/spl_array.h +++ b/ext/spl/spl_array.h @@ -27,10 +27,6 @@ #define SPL_ARRAY_INT_MASK 0xFFFF0000 #define SPL_ARRAY_CLONE_MASK 0x0100FFFF -#define SPL_ARRAY_METHOD_NO_ARG 0 -#define SPL_ARRAY_METHOD_CALLBACK_ARG 1 -#define SPL_ARRAY_METHOD_SORT_FLAGS_ARG 2 - extern PHPAPI zend_class_entry *spl_ce_ArrayObject; extern PHPAPI zend_class_entry *spl_ce_ArrayIterator; extern PHPAPI zend_class_entry *spl_ce_RecursiveArrayIterator; diff --git a/ext/spl/tests/ArrayObject/asort_disabled.phpt b/ext/spl/tests/ArrayObject/asort_disabled.phpt new file mode 100644 index 0000000000000..8f2241332f72e --- /dev/null +++ b/ext/spl/tests/ArrayObject/asort_disabled.phpt @@ -0,0 +1,18 @@ +--TEST-- +ArrayObject when function asort() is disabled +--INI-- +disable_functions=asort +--FILE-- +asort(); +var_dump($ao); + +?> +--EXPECTF-- +Fatal error: Uncaught Error: Cannot call method asort when function asort is disabled in %s:%d +Stack trace: +#0 %s(%d): ArrayObject->asort() +#1 {main} + thrown in %s on line %d diff --git a/ext/spl/tests/ArrayObject/ksort_disabled.phpt b/ext/spl/tests/ArrayObject/ksort_disabled.phpt new file mode 100644 index 0000000000000..258057ad64d31 --- /dev/null +++ b/ext/spl/tests/ArrayObject/ksort_disabled.phpt @@ -0,0 +1,18 @@ +--TEST-- +ArrayObject when function ksort() is disabled +--INI-- +disable_functions=ksort +--FILE-- +ksort(); +var_dump($ao); + +?> +--EXPECTF-- +Fatal error: Uncaught Error: Cannot call method ksort when function ksort is disabled in %s:%d +Stack trace: +#0 %s(%d): ArrayObject->ksort() +#1 {main} + thrown in %s on line %d diff --git a/ext/spl/tests/ArrayObject/natcasesort_disabled.phpt b/ext/spl/tests/ArrayObject/natcasesort_disabled.phpt new file mode 100644 index 0000000000000..336e1245dabc5 --- /dev/null +++ b/ext/spl/tests/ArrayObject/natcasesort_disabled.phpt @@ -0,0 +1,18 @@ +--TEST-- +ArrayObject when function natcasesort() is disabled +--INI-- +disable_functions=natcasesort +--FILE-- +natcasesort(); +var_dump($ao); + +?> +--EXPECTF-- +Fatal error: Uncaught Error: Cannot call method natcasesort when function natcasesort is disabled in %s:%d +Stack trace: +#0 %s(%d): ArrayObject->natcasesort() +#1 {main} + thrown in %s on line %d diff --git a/ext/spl/tests/ArrayObject/natsort_disabled.phpt b/ext/spl/tests/ArrayObject/natsort_disabled.phpt new file mode 100644 index 0000000000000..b674235627adb --- /dev/null +++ b/ext/spl/tests/ArrayObject/natsort_disabled.phpt @@ -0,0 +1,18 @@ +--TEST-- +ArrayObject when function natsort() is disabled +--INI-- +disable_functions=natsort +--FILE-- +natsort(); +var_dump($ao); + +?> +--EXPECTF-- +Fatal error: Uncaught Error: Cannot call method natsort when function natsort is disabled in %s:%d +Stack trace: +#0 %s(%d): ArrayObject->natsort() +#1 {main} + thrown in %s on line %d diff --git a/ext/spl/tests/ArrayObject/uasort_disabled.phpt b/ext/spl/tests/ArrayObject/uasort_disabled.phpt new file mode 100644 index 0000000000000..5a5e9aa57b21a --- /dev/null +++ b/ext/spl/tests/ArrayObject/uasort_disabled.phpt @@ -0,0 +1,18 @@ +--TEST-- +ArrayObject when function uasort() is disabled +--INI-- +disable_functions=uasort +--FILE-- +uasort(fn ($l, $r) => $l <=> $r); +var_dump($ao); + +?> +--EXPECTF-- +Fatal error: Uncaught Error: Cannot call method uasort when function uasort is disabled in %s:%d +Stack trace: +#0 %s(%d): ArrayObject->uasort(Object(Closure)) +#1 {main} + thrown in %s on line %d diff --git a/ext/spl/tests/ArrayObject/uksort_disabled.phpt b/ext/spl/tests/ArrayObject/uksort_disabled.phpt new file mode 100644 index 0000000000000..af703883a3f55 --- /dev/null +++ b/ext/spl/tests/ArrayObject/uksort_disabled.phpt @@ -0,0 +1,18 @@ +--TEST-- +ArrayObject when function uksort() is disabled +--INI-- +disable_functions=uksort +--FILE-- +uksort(fn ($l, $r) => $l <=> $r); +var_dump($ao); + +?> +--EXPECTF-- +Fatal error: Uncaught Error: Cannot call method uksort when function uksort is disabled in %s:%d +Stack trace: +#0 %s(%d): ArrayObject->uksort(Object(Closure)) +#1 {main} + thrown in %s on line %d