- Improve ARG_INFO() macros to support supplying required_num_args

- Initial fix for foreach($o->mthd()->arr) crash (now leaks)
This commit is contained in:
Zeev Suraski 2004-02-25 14:56:45 +00:00
parent ab968b3d03
commit 7086634a0b
5 changed files with 21 additions and 9 deletions

View File

@ -1221,7 +1221,11 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, zend_function_entr
internal_function->arg_info = ptr->arg_info+1;
internal_function->num_args = ptr->num_args;
/* Currently you cannot denote that the function can accept less arguments than num_args */
internal_function->required_num_args = ptr->num_args;
if (ptr->arg_info[0].required_num_args == -1) {
internal_function->required_num_args = ptr->num_args;
} else {
internal_function->required_num_args = ptr->arg_info[0].required_num_args;
}
internal_function->pass_rest_by_reference = ptr->arg_info[0].pass_by_reference;
internal_function->return_reference = ptr->arg_info[0].return_reference;
} else {

View File

@ -57,14 +57,14 @@ typedef struct _zend_function_entry {
ZEND_FENTRY(name, ZEND_FN(classname##_##alias), arg_info, flags)
#define ZEND_ME_MAPPING(name, func_name, arg_types) ZEND_NAMED_FE(name, ZEND_FN(func_name), arg_types)
#define ZEND_ARG_INFO(pass_by_ref, name) { #name, sizeof(#name)-1, NULL, 0, 0, pass_by_ref, 0 },
#define ZEND_ARG_PASS_INFO(pass_by_ref) { NULL, 0, NULL, 0, 0, pass_by_ref, 0 },
#define ZEND_ARG_OBJ_INFO(pass_by_ref, name, classname, allow_null) { #name, sizeof(#name)-1, #classname, sizeof(#classname)-1, allow_null, pass_by_ref, 0 },
#define ZEND_BEGIN_ARG_INFO_EX(name, pass_rest_by_reference, return_reference) \
zend_arg_info name[] = { \
{ NULL, 0, NULL, 0, 0, pass_rest_by_reference, return_reference },
#define ZEND_ARG_INFO(pass_by_ref, name) { #name, sizeof(#name)-1, NULL, 0, 0, pass_by_ref, 0, 0 },
#define ZEND_ARG_PASS_INFO(pass_by_ref) { NULL, 0, NULL, 0, 0, pass_by_ref, 0, 0 },
#define ZEND_ARG_OBJ_INFO(pass_by_ref, name, classname, allow_null) { #name, sizeof(#name)-1, #classname, sizeof(#classname)-1, allow_null, pass_by_ref, 0, 0 },
#define ZEND_BEGIN_ARG_INFO_EX(name, pass_rest_by_reference, return_reference, required_num_args) \
zend_arg_info name[] = { \
{ NULL, 0, NULL, 0, 0, pass_rest_by_reference, return_reference, required_num_args },
#define ZEND_BEGIN_ARG_INFO(name, pass_rest_by_reference) \
ZEND_BEGIN_ARG_INFO_EX(name, pass_rest_by_reference, ZEND_RETURN_REFERENCE_AGNOSTIC)
ZEND_BEGIN_ARG_INFO_EX(name, pass_rest_by_reference, ZEND_RETURN_REFERENCE_AGNOSTIC, -1)
#define ZEND_END_ARG_INFO() };
/* Name macros */

View File

@ -1713,7 +1713,7 @@ static zend_bool zend_do_perform_implementation_check(zend_function *fe)
zend_uint i;
zend_function *proto = fe->common.prototype;
if (!proto) {
if (!proto || !proto->common.arg_info) {
return 1;
}
@ -3275,6 +3275,10 @@ void zend_do_foreach_begin(znode *foreach_token, znode *array, znode *open_brack
is_variable = 1;
}
zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC);
if (CG(active_op_array)->opcodes[CG(active_op_array)->last-1].opcode == ZEND_FETCH_OBJ_W) {
/* FIXME: This will cause a leak, we have to unlock at the end of foreach() */
CG(active_op_array)->opcodes[CG(active_op_array)->last-1].extended_value |= ZEND_FETCH_ADD_LOCK;
}
} else {
is_variable = 0;
}

View File

@ -141,6 +141,7 @@ typedef struct _zend_arg_info {
zend_bool allow_null;
zend_bool pass_by_reference;
zend_bool return_reference;
int required_num_args;
} zend_arg_info;
struct _zend_op_array {

View File

@ -2040,6 +2040,9 @@ int zend_fetch_obj_r_handler(ZEND_OPCODE_HANDLER_ARGS)
int zend_fetch_obj_w_handler(ZEND_OPCODE_HANDLER_ARGS)
{
if (opline->extended_value == ZEND_FETCH_ADD_LOCK) {
PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr);
}
zend_fetch_property_address(&opline->result, &opline->op1, &opline->op2, EX(Ts), BP_VAR_W TSRMLS_CC);
NEXT_OPCODE();
}