Skip to content
Closed
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
4 changes: 2 additions & 2 deletions Zend/zend_API.c
Original file line number Diff line number Diff line change
Expand Up @@ -3045,7 +3045,6 @@ ZEND_API zend_result zend_register_functions(zend_class_entry *scope, const zend
internal_function->prop_info = NULL;
internal_function->attributes = NULL;
internal_function->frameless_function_infos = ptr->frameless_function_infos;
internal_function->fn_flags2 = 0;
if (EG(active)) { // at run-time: this ought to only happen if registered with dl() or somehow temporarily at runtime
ZEND_MAP_PTR_INIT(internal_function->run_time_cache, zend_arena_calloc(&CG(arena), 1, zend_internal_run_time_cache_reserved_size()));
} else {
Expand All @@ -3055,7 +3054,7 @@ ZEND_API zend_result zend_register_functions(zend_class_entry *scope, const zend
ZEND_MAP_PTR_INIT(internal_function->run_time_cache, NULL);
#endif
}
if (ptr->flags) {
if (ptr->flags & UINT32_MAX) {
if (!(ptr->flags & ZEND_ACC_PPP_MASK)) {
if (ptr->flags != ZEND_ACC_DEPRECATED && scope) {
zend_error(error_type, "Invalid access level for %s::%s() - access must be exactly one of public, protected or private", ZSTR_VAL(scope->name), ptr->fname);
Expand All @@ -3067,6 +3066,7 @@ ZEND_API zend_result zend_register_functions(zend_class_entry *scope, const zend
} else {
internal_function->fn_flags = ZEND_ACC_PUBLIC;
}
internal_function->fn_flags2 = ptr->flags >> 32;

if (ptr->arg_info) {
zend_internal_function_info *info = (zend_internal_function_info*)ptr->arg_info;
Expand Down
6 changes: 5 additions & 1 deletion Zend/zend_API.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ typedef struct _zend_function_entry {
zif_handler handler;
const struct _zend_internal_arg_info *arg_info;
uint32_t num_args;
uint32_t flags;
uint64_t flags;
const zend_frameless_function_info *frameless_function_infos;
const char *doc_comment;
} zend_function_entry;
Expand Down Expand Up @@ -74,6 +74,8 @@ typedef struct _zend_fcall_info_cache {
#define ZEND_FUNCTION(name) ZEND_NAMED_FUNCTION(zif_##name)
#define ZEND_METHOD(classname, name) ZEND_NAMED_FUNCTION(zim_##classname##_##name)

#define ZEND_FENTRY_FLAGS(flags, flags2) (((uint64_t)flags) | ((uint64_t)flags2 << 32))

#define ZEND_FENTRY(zend_name, name, arg_info, flags) { #zend_name, name, arg_info, (uint32_t) (sizeof(arg_info)/sizeof(struct _zend_internal_arg_info)-1), flags, NULL, NULL },

#define ZEND_RAW_FENTRY(zend_name, name, arg_info, flags, frameless_function_infos, doc_comment) { zend_name, name, arg_info, (uint32_t) (sizeof(arg_info)/sizeof(struct _zend_internal_arg_info)-1), flags, frameless_function_infos, doc_comment },
Expand Down Expand Up @@ -894,6 +896,8 @@ static zend_always_inline zend_result zend_forbid_dynamic_call(void)
const zend_execute_data *ex = EG(current_execute_data);
ZEND_ASSERT(ex != NULL && ex->func != NULL);

ZEND_ASSERT(ex->func->common.fn_flags2 & ZEND_ACC2_FORBID_DYN_CALLS);

if (ZEND_CALL_INFO(ex) & ZEND_CALL_DYNAMIC) {
zend_string *function_or_method_name = get_active_function_or_method_name();
zend_throw_error(NULL, "Cannot call %.*s() dynamically",
Expand Down
1 change: 1 addition & 0 deletions Zend/zend_builtin_functions.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
+----------------------------------------------------------------------+
*/

#include "php_version.h"
#include "zend.h"
#include "zend_API.h"
#include "zend_attributes.h"
Expand Down
8 changes: 7 additions & 1 deletion Zend/zend_builtin_functions.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,16 @@ function die(string|int $status = 0): never {}
/** @refcount 1 */
function zend_version(): string {}

/** @forbid-dynamic-calls */
function func_num_args(): int {}

/** @forbid-dynamic-calls */
function func_get_arg(int $position): mixed {}

/** @return array<int, mixed> */
/**
* @return array<int, mixed>
* @forbid-dynamic-calls
*/
function func_get_args(): array {}

function strlen(string $string): int {}
Expand Down Expand Up @@ -156,6 +161,7 @@ function get_defined_functions(bool $exclude_disabled = true): array {}
/**
* @return array<string, mixed|ref>
* @refcount 1
* @forbid-dynamic-calls
*/
function get_defined_vars(): array {}

Expand Down
26 changes: 21 additions & 5 deletions Zend/zend_builtin_functions_arginfo.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Zend/zend_closures.c
Original file line number Diff line number Diff line change
Expand Up @@ -749,6 +749,7 @@ static ZEND_NAMED_FUNCTION(zend_closure_internal_handler) /* {{{ */
{
zend_closure *closure = (zend_closure*)ZEND_CLOSURE_OBJECT(EX(func));
closure->orig_internal_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU);
ZEND_ASSERT(!(closure->func.common.fn_flags2 & ZEND_ACC2_FORBID_DYN_CALLS) || EG(exception));
// Assign to EX(this) so that it is released after observer checks etc.
ZEND_ADD_CALL_FLAG(execute_data, ZEND_CALL_RELEASE_THIS);
Z_OBJ(EX(This)) = &closure->std;
Expand Down
5 changes: 3 additions & 2 deletions Zend/zend_compile.h
Original file line number Diff line number Diff line change
Expand Up @@ -412,10 +412,11 @@ typedef struct _zend_oparray_context {
/* op_array uses strict mode types | | | */
#define ZEND_ACC_STRICT_TYPES (1U << 31) /* | X | | */
/* | | | */
/* Function Flags 2 (fn_flags2) (unused: 0-31) | | | */
/* Function Flags 2 (fn_flags2) (unused: 1-31) | | | */
/* ============================ | | | */
/* | | | */
/* #define ZEND_ACC2_EXAMPLE (1 << 0) | X | | */
/* Function forbids dynamic calls | | | */
#define ZEND_ACC2_FORBID_DYN_CALLS (1 << 0) /* | X | | */

#define ZEND_ACC_PPP_MASK (ZEND_ACC_PUBLIC | ZEND_ACC_PROTECTED | ZEND_ACC_PRIVATE)
#define ZEND_ACC_PPP_SET_MASK (ZEND_ACC_PUBLIC_SET | ZEND_ACC_PROTECTED_SET | ZEND_ACC_PRIVATE_SET)
Expand Down
1 change: 1 addition & 0 deletions Zend/zend_execute_API.c
Original file line number Diff line number Diff line change
Expand Up @@ -1030,6 +1030,7 @@ zend_result zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_
}
ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)
? Z_ISREF_P(fci->retval) : !Z_ISREF_P(fci->retval));
ZEND_ASSERT(!(call->func->common.fn_flags2 & ZEND_ACC2_FORBID_DYN_CALLS));
}
#endif
ZEND_OBSERVER_FCALL_END(call, fci->retval);
Expand Down
8 changes: 8 additions & 0 deletions Zend/zend_vm_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -4160,6 +4160,8 @@ ZEND_VM_HOT_HANDLER(129, ZEND_DO_ICALL, ANY, ANY, SPEC(RETVAL,OBSERVER))
ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)
? Z_ISREF_P(ret) : !Z_ISREF_P(ret));
zend_verify_internal_func_info(call->func, ret);
ZEND_ASSERT(!(ZEND_CALL_INFO(call) & ZEND_CALL_DYNAMIC)
|| !(call->func->common.fn_flags2 & ZEND_ACC2_FORBID_DYN_CALLS));
}
#endif
ZEND_OBSERVER_FCALL_END(call, EG(exception) ? NULL : ret);
Expand Down Expand Up @@ -4291,6 +4293,8 @@ ZEND_VM_HOT_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL,OBSERVER))
ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)
? Z_ISREF_P(ret) : !Z_ISREF_P(ret));
zend_verify_internal_func_info(call->func, ret);
ZEND_ASSERT(!(ZEND_CALL_INFO(call) & ZEND_CALL_DYNAMIC)
|| !(call->func->common.fn_flags2 & ZEND_ACC2_FORBID_DYN_CALLS));
}
ZEND_ASSERT(opline->result_type != IS_TMP_VAR || !Z_ISREF_P(ret));
#endif
Expand Down Expand Up @@ -4422,6 +4426,8 @@ ZEND_VM_HOT_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL,OBSERVER))
ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)
? Z_ISREF_P(ret) : !Z_ISREF_P(ret));
zend_verify_internal_func_info(call->func, ret);
ZEND_ASSERT(!(ZEND_CALL_INFO(call) & ZEND_CALL_DYNAMIC)
|| !(call->func->common.fn_flags2 & ZEND_ACC2_FORBID_DYN_CALLS));
}
ZEND_ASSERT(opline->result_type != IS_TMP_VAR || !Z_ISREF_P(ret));
#endif
Expand Down Expand Up @@ -9131,6 +9137,8 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY, SPEC(OBSERVER))
ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)
? Z_ISREF_P(ret) : !Z_ISREF_P(ret));
zend_verify_internal_func_info(call->func, ret);
ZEND_ASSERT(!(ZEND_CALL_INFO(call) & ZEND_CALL_DYNAMIC)
|| !(call->func->common.fn_flags2 & ZEND_ACC2_FORBID_DYN_CALLS));
}
#endif
ZEND_OBSERVER_FCALL_END(call, EG(exception) ? NULL : ret);
Expand Down
44 changes: 44 additions & 0 deletions Zend/zend_vm_execute.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading