}
RFC: https://wiki.php.net/rfc/abstract_trait_method_validation
+ . Disabled functions are now treated exactly like non-existent functions.
+ Calling a disabled function will report it as unknown, and redefining a
+ disabled function is now possible.
- COM:
. Removed the ability to import case-insensitive constants from type
4. Deprecated Functionality
========================================
+- Core:
+ . Calling get_defined_functions() with $exclude_disabled explicitly set to
+ false is deprecated. get_defined_functions() will never include disabled
+ functions.
+
- Enchant:
. enchant_broker_set_dict_path and enchant_broker_get_dict_path
not available in libenchant < 1.5 nor in libenchant-2
do not accept empty files as valid zip archives any longer.
Existing workaround will be removed in next version.
+- Reflection:
+ . ReflectionFunction::isDisabled() is deprecated, as it is no longer possible
+ to create a ReflectionFunction for a disabled function. This method now
+ always returns false.
+
========================================
5. Changed Functions
========================================
var_dump(function_exists("strlen"));
var_dump(is_callable("strlen"));
-var_dump(strlen("xxx"));
-var_dump(defined("PHP_VERSION"));
-var_dump(constant("PHP_VERSION"));
-var_dump(call_user_func("strlen"));
-var_dump(is_string("xxx"));
-var_dump(is_string());
+try {
+ var_dump(strlen("xxx"));
+} catch (Error $e) {
+ echo $e->getMessage(), "\n";
+}
+try {
+ var_dump(defined("PHP_VERSION"));
+} catch (Error $e) {
+ echo $e->getMessage(), "\n";
+}
+try {
+ var_dump(constant("PHP_VERSION"));
+} catch (Error $e) {
+ echo $e->getMessage(), "\n";
+}
+try {
+ var_dump(call_user_func("strlen"));
+} catch (Error $e) {
+ echo $e->getMessage(), "\n";
+}
+try {
+ var_dump(is_string("xxx"));
+} catch (Error $e) {
+ echo $e->getMessage(), "\n";
+}
+try {
+ var_dump(is_string());
+} catch (Error $e) {
+ echo $e->getMessage(), "\n";
+}
?>
---EXPECTF--
+--EXPECT--
bool(false)
-bool(true)
-
-Warning: strlen() has been disabled for security reasons in %sbug69315.php on line %d
-NULL
-
-Warning: defined() has been disabled for security reasons in %sbug69315.php on line %d
-NULL
-
-Warning: constant() has been disabled for security reasons in %sbug69315.php on line %d
-NULL
-
-Warning: call_user_func() has been disabled for security reasons in %sbug69315.php on line %d
-NULL
-
-Warning: is_string() has been disabled for security reasons in %sbug69315.php on line %d
-NULL
-
-Warning: is_string() has been disabled for security reasons in %s on line %d
-NULL
+bool(false)
+Call to undefined function strlen()
+Call to undefined function defined()
+Call to undefined function constant()
+Call to undefined function call_user_func()
+Call to undefined function is_string()
+Call to undefined function is_string()
--- /dev/null
+--TEST--
+Bug #79382: Cannot redeclare disabled function
+--INI--
+disable_functions=strlen
+--FILE--
+<?php
+
+function strlen(string $x): int {
+ $len = 0;
+ while (isset($x[$len])) $len++;
+ return $len;
+}
+
+var_dump(strlen("foobar"));
+
+?>
+--EXPECT--
+int(6)
--FILE--
<?php
-phpinfo();
+try {
+ phpinfo();
+} catch (Error $e) {
+ echo $e->getMessage(), "\n";
+}
-echo "Done\n";
?>
---EXPECTF--
-Warning: phpinfo() has been disabled for security reasons in %s on line %d
-Done
+--EXPECT--
+Call to undefined function phpinfo()
/* Disabled functions support */
-/* {{{ proto void display_disabled_function(void)
-Dummy function which displays an error when a disabled function is called. */
-ZEND_API ZEND_COLD ZEND_FUNCTION(display_disabled_function)
-{
- zend_error(E_WARNING, "%s() has been disabled for security reasons", get_active_function_name());
-}
-/* }}} */
-
ZEND_API int zend_disable_function(char *function_name, size_t function_name_length) /* {{{ */
{
- zend_internal_function *func;
- if ((func = zend_hash_str_find_ptr(CG(function_table), function_name, function_name_length))) {
- zend_free_internal_arg_info(func);
- func->fn_flags &= ~(ZEND_ACC_VARIADIC | ZEND_ACC_HAS_TYPE_HINTS | ZEND_ACC_HAS_RETURN_TYPE);
- func->num_args = 0;
- func->required_num_args = 0;
- func->arg_info = NULL;
- func->handler = ZEND_FN(display_disabled_function);
- return SUCCESS;
- }
- return FAILURE;
+ return zend_hash_str_del(CG(function_table), function_name, function_name_length);
}
/* }}} */
ZEND_API zend_bool zend_is_countable(zval *countable);
-ZEND_API ZEND_FUNCTION(display_disabled_function);
-
ZEND_API int zend_get_default_from_internal_arg_info(
zval *default_value_zval, zend_internal_arg_info *arg_info);
ZEND_FUNCTION(function_exists)
{
zend_string *name;
- zend_function *func;
+ zend_bool exists;
zend_string *lcname;
ZEND_PARSE_PARAMETERS_START(1, 1)
lcname = zend_string_tolower(name);
}
- func = zend_hash_find_ptr(EG(function_table), lcname);
+ exists = zend_hash_exists(EG(function_table), lcname);
zend_string_release_ex(lcname, 0);
- /*
- * A bit of a hack, but not a bad one: we see if the handler of the function
- * is actually one that displays "function is disabled" message.
- */
- RETURN_BOOL(func && (func->type != ZEND_INTERNAL_FUNCTION ||
- func->internal_function.handler != zif_display_disabled_function));
+ RETURN_BOOL(exists);
}
/* }}} */
zval internal, user;
zend_string *key;
zend_function *func;
- zend_bool exclude_disabled = 0;
- char *disable_functions = NULL;
+ zend_bool exclude_disabled = 1;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &exclude_disabled) == FAILURE) {
RETURN_THROWS();
}
+ if (exclude_disabled == 0) {
+ zend_error(E_DEPRECATED,
+ "get_defined_functions(): Setting $exclude_disabled to false has no effect");
+ }
+
array_init(&internal);
array_init(&user);
array_init(return_value);
- if (exclude_disabled) {
- disable_functions = INI_STR("disable_functions");
- }
ZEND_HASH_FOREACH_STR_KEY_PTR(EG(function_table), key, func) {
if (key && ZSTR_VAL(key)[0] != 0) {
if (func->type == ZEND_INTERNAL_FUNCTION) {
- if (disable_functions != NULL) {
- if (strstr(disable_functions, func->common.function_name->val) == NULL) {
- add_next_index_str(&internal, zend_string_copy(key));
- }
- } else {
- add_next_index_str(&internal, zend_string_copy(key));
- }
+ add_next_index_str(&internal, zend_string_copy(key));
} else if (func->type == ZEND_USER_FUNCTION) {
add_next_index_str(&user, zend_string_copy(key));
}
function get_declared_interfaces(): array {}
-function get_defined_functions(bool $exclude_disabled = false): array {}
+function get_defined_functions(bool $exclude_disabled = true): array {}
function get_defined_vars(): array {}
#define arginfo_get_declared_interfaces arginfo_func_get_args
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_get_defined_functions, 0, 0, IS_ARRAY, 0)
- ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, exclude_disabled, _IS_BOOL, 0, "false")
+ ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, exclude_disabled, _IS_BOOL, 0, "true")
ZEND_END_ARG_INFO()
#define arginfo_get_defined_vars arginfo_func_get_args
int zend_try_compile_special_func(znode *result, zend_string *lcname, zend_ast_list *args, zend_function *fbc, uint32_t type) /* {{{ */
{
- if (fbc->internal_function.handler == ZEND_FN(display_disabled_function)) {
- return FAILURE;
- }
-
if (CG(compiler_options) & ZEND_COMPILE_NO_BUILTINS) {
return FAILURE;
}
Z_TYPE(ZEND_OP1_LITERAL(send1_opline)) == IS_STRING) {
if ((Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("function_exists")-1 &&
!memcmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)),
- "function_exists", sizeof("function_exists")-1) &&
- !zend_optimizer_is_disabled_func("function_exists", sizeof("function_exists") - 1)) ||
+ "function_exists", sizeof("function_exists")-1)) ||
(Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("is_callable")-1 &&
!memcmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)),
- "is_callable", sizeof("is_callable")) &&
- !zend_optimizer_is_disabled_func("is_callable", sizeof("is_callable") - 1))) {
+ "is_callable", sizeof("is_callable")))) {
zend_internal_function *func;
zend_string *lc_name = zend_string_tolower(
Z_STR(ZEND_OP1_LITERAL(send1_opline)));
#endif
) {
zval t;
- if (Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("is_callable") - 1 ||
- func->handler != ZEND_FN(display_disabled_function)) {
- ZVAL_TRUE(&t);
- } else {
- ZVAL_FALSE(&t);
- }
+ ZVAL_TRUE(&t);
literal_dtor(&ZEND_OP2_LITERAL(init_opline));
MAKE_NOP(init_opline);
literal_dtor(&ZEND_OP1_LITERAL(send1_opline));
break;
} else if (Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("extension_loaded")-1 &&
!memcmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)),
- "extension_loaded", sizeof("extension_loaded")-1) &&
- !zend_optimizer_is_disabled_func("extension_loaded", sizeof("extension_loaded") - 1)) {
+ "extension_loaded", sizeof("extension_loaded")-1)) {
zval t;
zend_string *lc_name = zend_string_tolower(
Z_STR(ZEND_OP1_LITERAL(send1_opline)));
break;
} else if (Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("constant")-1 &&
!memcmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)),
- "constant", sizeof("constant")-1) &&
- !zend_optimizer_is_disabled_func("constant", sizeof("constant") - 1)) {
+ "constant", sizeof("constant")-1)) {
zval t;
if (zend_optimizer_get_persistent_constant(Z_STR(ZEND_OP1_LITERAL(send1_opline)), &t, 1)) {
} else if (Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("dirname")-1 &&
!memcmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)),
"dirname", sizeof("dirname") - 1) &&
- !zend_optimizer_is_disabled_func("dirname", sizeof("dirname") - 1) &&
IS_ABSOLUTE_PATH(Z_STRVAL(ZEND_OP1_LITERAL(send1_opline)), Z_STRLEN(ZEND_OP1_LITERAL(send1_opline)))) {
zend_string *dirname = zend_string_init(Z_STRVAL(ZEND_OP1_LITERAL(send1_opline)), Z_STRLEN(ZEND_OP1_LITERAL(send1_opline)), 0);
ZSTR_LEN(dirname) = zend_dirname(ZSTR_VAL(dirname), ZSTR_LEN(dirname));
}
func = zend_hash_find_ptr(CG(function_table), name);
- if (!func || func->type != ZEND_INTERNAL_FUNCTION
- || func->internal_function.handler == ZEND_FN(display_disabled_function)) {
+ if (!func || func->type != ZEND_INTERNAL_FUNCTION) {
return FAILURE;
}
}
func_info_t *info = Z_PTR_P(zv);
- if (UNEXPECTED(zend_optimizer_is_disabled_func(info->name, info->name_len))) {
- return MAY_BE_NULL;
- } else if (info->info_func) {
+ if (info->info_func) {
return info->info_func(call_info, ssa);
} else {
return info->info;
return zend_optimizer_add_literal(op_array, &zv);
}
-int zend_optimizer_is_disabled_func(const char *name, size_t len) {
- zend_function *fbc = (zend_function *)zend_hash_str_find_ptr(EG(function_table), name, len);
-
- return (fbc && fbc->type == ZEND_INTERNAL_FUNCTION &&
- fbc->internal_function.handler == ZEND_FN(display_disabled_function));
-}
-
static inline void drop_leading_backslash(zval *val) {
if (Z_STRVAL_P(val)[0] == '\\') {
zend_string *str = zend_string_init(Z_STRVAL_P(val) + 1, Z_STRLEN_P(val) - 1, 0);
void zend_optimizer_nop_removal(zend_op_array *op_array, zend_optimizer_ctx *ctx);
void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx *ctx);
void zend_optimizer_compact_vars(zend_op_array *op_array);
-int zend_optimizer_is_disabled_func(const char *name, size_t len);
zend_function *zend_optimizer_get_called_func(
zend_script *script, zend_op_array *op_array, zend_op *opline, zend_bool *is_prototype);
uint32_t zend_optimizer_classify_function(zend_string *name, uint32_t num_args);
--FILE--
<?php
var_dump(is_callable("dl"));
-dl("a.so");
+try {
+ dl("a.so");
+} catch (Error $e) {
+ echo $e->getMessage(), "\n";
+}
?>
---EXPECTF--
-bool(true)
-
-Warning: dl() has been disabled for security reasons in %sbug68104.php on line %d
+--EXPECT--
+bool(false)
+Call to undefined function dl()
--FILE--
<?php
-var_dump(strpos('foo', 'bar'));
+try {
+ var_dump(strpos('foo', 'bar'));
+} catch (Error $e) {
+ echo $e->getMessage(), "\n";
+}
?>
---EXPECTF--
-Warning: strpos() has been disabled for security reasons in %s on line %d
-NULL
+--EXPECT--
+Call to undefined function strpos()
Returns whether this function has been disabled or not */
ZEND_METHOD(ReflectionFunction, isDisabled)
{
- reflection_object *intern;
- zend_function *fptr;
-
- GET_REFLECTION_OBJECT_PTR(fptr);
-
if (zend_parse_parameters_none() == FAILURE) {
RETURN_THROWS();
}
- RETURN_BOOL(fptr->type == ZEND_INTERNAL_FUNCTION && fptr->internal_function.handler == zif_display_disabled_function);
+ /* A disabled function cannot be queried using Reflection. */
+ RETURN_FALSE;
}
/* }}} */
public function __toString(): string {}
- /** @return bool */
+ /**
+ * @return bool
+ * @deprecated ReflectionFunction can no longer be constructed for disabled functions
+ */
public function isDisabled() {}
/** @return mixed */
static const zend_function_entry class_ReflectionFunction_methods[] = {
ZEND_ME(ReflectionFunction, __construct, arginfo_class_ReflectionFunction___construct, ZEND_ACC_PUBLIC)
ZEND_ME(ReflectionFunction, __toString, arginfo_class_ReflectionFunction___toString, ZEND_ACC_PUBLIC)
- ZEND_ME(ReflectionFunction, isDisabled, arginfo_class_ReflectionFunction_isDisabled, ZEND_ACC_PUBLIC)
+ ZEND_ME(ReflectionFunction, isDisabled, arginfo_class_ReflectionFunction_isDisabled, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED)
ZEND_ME(ReflectionFunction, invoke, arginfo_class_ReflectionFunction_invoke, ZEND_ACC_PUBLIC)
ZEND_ME(ReflectionFunction, invokeArgs, arginfo_class_ReflectionFunction_invokeArgs, ZEND_ACC_PUBLIC)
ZEND_ME(ReflectionFunction, getClosure, arginfo_class_ReflectionFunction_getClosure, ZEND_ACC_PUBLIC)
disable_functions=is_file
--FILE--
<?php
-$rc = new ReflectionFunction('is_file');
-var_dump($rc->isDisabled());
+try {
+ $rf = new ReflectionFunction('is_file');
+ var_dump($rf->isDisabled());
+} catch (ReflectionException $e) {
+ echo $e->getMessage(), "\n";
+}
+
+$rf = new ReflectionFunction('is_string');
+var_dump($rf->isDisabled());
?>
---EXPECT--
-bool(true)
+--EXPECTF--
+Function is_file() does not exist
+
+Deprecated: Function ReflectionFunction::isDisabled() is deprecated in %s on line %d
+bool(false)
<?php
$disabled_function = 'dl';
+/* exclude_disabled parameters is harded to true */
+
$functions = get_defined_functions();
var_dump(in_array($disabled_function, $functions['internal']));
$functions = get_defined_functions(true);
var_dump(in_array($disabled_function, $functions['internal']));
?>
---EXPECT--
-bool(true)
-bool(true)
+--EXPECTF--
+bool(false)
+
+Deprecated: get_defined_functions(): Setting $exclude_disabled to false has no effect in %s on line %d
+bool(false)
bool(false)