Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 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.

3 changes: 3 additions & 0 deletions Zend/zend_closures.c
Original file line number Diff line number Diff line change
Expand Up @@ -749,6 +749,9 @@ 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);
#if ZEND_DEBUG
ZEND_ASSERT(!(closure->func.common.fn_flags2 & ZEND_ACC2_FORBID_DYN_CALLS) || EG(exception));
#endif
Comment thread
arnaud-lb marked this conversation as resolved.
Outdated
// 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
12 changes: 12 additions & 0 deletions Zend/zend_vm_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -4160,6 +4160,9 @@ 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);
if (ZEND_CALL_INFO(call) & ZEND_CALL_DYNAMIC) {
ZEND_ASSERT(!(call->func->common.fn_flags2 & ZEND_ACC2_FORBID_DYN_CALLS));
}
Comment thread
TimWolla marked this conversation as resolved.
Outdated
}
#endif
ZEND_OBSERVER_FCALL_END(call, EG(exception) ? NULL : ret);
Expand Down Expand Up @@ -4291,6 +4294,9 @@ 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);
if (ZEND_CALL_INFO(call) & ZEND_CALL_DYNAMIC) {
ZEND_ASSERT(!(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 +4428,9 @@ 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);
if (ZEND_CALL_INFO(call) & ZEND_CALL_DYNAMIC) {
ZEND_ASSERT(!(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 +9140,9 @@ 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);
if (ZEND_CALL_INFO(call) & ZEND_CALL_DYNAMIC) {
ZEND_ASSERT(!(call->func->common.fn_flags2 & ZEND_ACC2_FORBID_DYN_CALLS));
}
}
#endif
ZEND_OBSERVER_FCALL_END(call, EG(exception) ? NULL : ret);
Expand Down
Loading
Loading