diff options
-rw-r--r-- | Zend/zend.h | 17 | ||||
-rw-r--r-- | Zend/zend_API.c | 11 | ||||
-rw-r--r-- | Zend/zend_API.h | 40 | ||||
-rw-r--r-- | Zend/zend_builtin_functions.c | 31 | ||||
-rw-r--r-- | Zend/zend_compile.c | 104 | ||||
-rw-r--r-- | Zend/zend_compile.h | 55 | ||||
-rw-r--r-- | Zend/zend_execute.c | 108 | ||||
-rw-r--r-- | Zend/zend_execute_API.c | 16 | ||||
-rw-r--r-- | Zend/zend_language_parser.y | 22 | ||||
-rw-r--r-- | Zend/zend_modules.h | 10 | ||||
-rw-r--r-- | Zend/zend_object_handlers.c | 3 | ||||
-rw-r--r-- | Zend/zend_opcode.c | 14 | ||||
-rw-r--r-- | Zend/zend_reflection_api.c | 2 | ||||
-rw-r--r-- | ext/reflection/php_reflection.c | 2 |
14 files changed, 241 insertions, 194 deletions
diff --git a/Zend/zend.h b/Zend/zend.h index 0fd5576610..2b61e3692e 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -262,15 +262,6 @@ struct _zval_struct { zend_uchar is_ref; }; -struct _zend_op_array; - -typedef struct _zend_function_entry { - char *fname; - void (*handler)(INTERNAL_FUNCTION_PARAMETERS); - unsigned char *func_arg_types; -} zend_function_entry; - - typedef struct _zend_property_reference { int type; /* read, write or r/w */ zval *object; @@ -306,7 +297,7 @@ struct _zend_class_entry { HashTable properties_info; HashTable *static_members; HashTable constants_table; - zend_function_entry *builtin_functions; + struct _zend_function_entry *builtin_functions; union _zend_function *constructor; union _zend_function *destructor; @@ -397,12 +388,6 @@ typedef int (*zend_write_func_t)(const char *str, uint str_length); #define OE_IS_METHOD (1<<2) -/* Argument passing types */ -#define BYREF_NONE 0 -#define BYREF_FORCE 1 -#define BYREF_ALLOW 2 -#define BYREF_FORCE_REST 3 - int zend_startup(zend_utility_functions *utility_functions, char **extensions, int start_builtin_functions); void zend_shutdown(TSRMLS_D); void zend_register_standard_ini_entries(TSRMLS_D); diff --git a/Zend/zend_API.c b/Zend/zend_API.c index c22cef4708..88faa34bd5 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -1158,11 +1158,20 @@ int zend_register_functions(zend_class_entry *scope, zend_function_entry *functi while (ptr->fname) { internal_function->handler = ptr->handler; - internal_function->arg_types = ptr->func_arg_types; internal_function->function_name = ptr->fname; internal_function->scope = scope; internal_function->fn_flags = ZEND_ACC_PUBLIC; internal_function->prototype = NULL; + if (ptr->arg_info) { + internal_function->arg_info = ptr->arg_info+1; + internal_function->num_args = ptr->num_args; + internal_function->pass_rest_by_reference = ptr->arg_info[0].pass_by_reference; + } else { + internal_function->arg_info = NULL; + internal_function->num_args = 0; + internal_function->pass_rest_by_reference = 0; + } + internal_function->fn_flags = ptr->flags; if (!internal_function->handler) { zend_error(error_type, "Null function defined as active function"); zend_unregister_functions(functions, count, target_function_table TSRMLS_CC); diff --git a/Zend/zend_API.h b/Zend/zend_API.h index b3606305c5..5a3abe20c4 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -32,16 +32,32 @@ BEGIN_EXTERN_C() -#define ZEND_FN(name) zif_##name -#define ZEND_NAMED_FUNCTION(name) void name(INTERNAL_FUNCTION_PARAMETERS) -#define ZEND_FUNCTION(name) ZEND_NAMED_FUNCTION(ZEND_FN(name)) -#define ZEND_METHOD(class, name) ZEND_NAMED_FUNCTION(ZEND_FN(class##_##name)) -#define ZEND_NAMED_FE(zend_name, name, arg_types) { #zend_name, name, arg_types }, -#define ZEND_FE(name, arg_types) ZEND_NAMED_FE(name, ZEND_FN(name), arg_types) -#define ZEND_FALIAS(name, alias, arg_types) ZEND_NAMED_FE(name, ZEND_FN(alias), arg_types) -#define ZEND_STATIC_FE(name, impl_name, arg_types) { name, impl_name, arg_types }, -#define ZEND_ME(class, name, arg_types) ZEND_NAMED_FE(name, ZEND_FN(class##_##name), arg_types) +typedef struct _zend_function_entry { + char *fname; + void (*handler)(INTERNAL_FUNCTION_PARAMETERS); + struct _zend_arg_info *arg_info; + zend_uint num_args; + zend_uint flags; +} zend_function_entry; + +#define ZEND_FN(name) zif_##name +#define ZEND_NAMED_FUNCTION(name) void name(INTERNAL_FUNCTION_PARAMETERS) +#define ZEND_FUNCTION(name) ZEND_NAMED_FUNCTION(ZEND_FN(name)) +#define ZEND_METHOD(classname, name) ZEND_NAMED_FUNCTION(ZEND_FN(classname##_##name)) + +#define ZEND_NAMED_FE(zend_name, name, arg_info) { #zend_name, name, arg_info, sizeof(arg_info)/sizeof(struct _zend_arg_info)-1, 0 }, +#define ZEND_FE(name, arg_info) ZEND_NAMED_FE(name, ZEND_FN(name), arg_info) +#define ZEND_FALIAS(name, alias, arg_info) ZEND_NAMED_FE(name, ZEND_FN(alias), arg_info) +#define ZEND_ME(classname, name, arg_info, flags) { #name, ZEND_FN(classname##_##name), arg_info, sizeof(arg_info)/sizeof(struct _zend_arg_info)-1, flags }, + +#define ZEND_ARG_INFO(pass_by_ref, name) { #name, sizeof(#name)-1, NULL, 0, 0, pass_by_ref }, +#define ZEND_ARG_PASS_INFO(pass_by_ref) { NULL, 0, NULL, 0, 0, pass_by_ref }, +#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 }, +#define ZEND_BEGIN_ARG_INFO(name, pass_rest_by_reference) \ + zend_arg_info name[] = { \ + ZEND_ARG_PASS_INFO(pass_rest_by_reference) +#define ZEND_END_ARG_INFO() }; /* Name macros */ #define ZEND_MODULE_STARTUP_N(module) zm_startup_##module @@ -249,9 +265,9 @@ ZEND_API int add_property_zval_ex(zval *arg, char *key, uint key_len, zval *valu #define add_property_stringl(__arg, __key, __str, __length, __duplicate) add_property_stringl_ex(__arg, __key, strlen(__key)+1, __str, __length, __duplicate TSRMLS_CC) #define add_property_zval(__arg, __key, __value) add_property_zval_ex(__arg, __key, strlen(__key)+1, __value TSRMLS_CC) -ZEND_API int call_user_function(HashTable *function_table, zval **object_pp, zval *function_name, zval *retval_ptr, int param_count, zval *params[] TSRMLS_DC); -ZEND_API int call_user_function_ex(HashTable *function_table, zval **object_pp, zval *function_name, zval **retval_ptr_ptr, int param_count, zval **params[], int no_separation, HashTable *symbol_table TSRMLS_DC); -ZEND_API int fast_call_user_function(HashTable *function_table, zval **object_pp, zval *function_name, zval **retval_ptr_ptr, int param_count, zval **params[], int no_separation, HashTable *symbol_table, zend_function **function_pointer TSRMLS_DC); +ZEND_API int call_user_function(HashTable *function_table, zval **object_pp, zval *function_name, zval *retval_ptr, zend_uint param_count, zval *params[] TSRMLS_DC); +ZEND_API int call_user_function_ex(HashTable *function_table, zval **object_pp, zval *function_name, zval **retval_ptr_ptr, zend_uint param_count, zval **params[], int no_separation, HashTable *symbol_table TSRMLS_DC); +ZEND_API int fast_call_user_function(HashTable *function_table, zval **object_pp, zval *function_name, zval **retval_ptr_ptr, zend_uint param_count, zval **params[], int no_separation, HashTable *symbol_table, zend_function **function_pointer TSRMLS_DC); ZEND_API int zend_set_hash_symbol(zval *symbol, char *name, int name_length, zend_bool is_ref, int num_symbol_tables, ...); diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index 6fc3017c3a..1032d79204 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -80,9 +80,33 @@ static ZEND_FUNCTION(zend_thread_id); #endif #endif -ZEND_API unsigned char first_arg_force_ref[] = { 1, BYREF_FORCE }; -ZEND_API unsigned char second_arg_force_ref[] = { 2, BYREF_NONE, BYREF_FORCE }; -ZEND_API unsigned char third_arg_force_ref[] = { 3, BYREF_NONE, BYREF_NONE, BYREF_FORCE }; +ZEND_API + ZEND_BEGIN_ARG_INFO(first_arg_force_ref, 0) + ZEND_ARG_PASS_INFO(1) + ZEND_END_ARG_INFO(); + + +ZEND_API + ZEND_BEGIN_ARG_INFO(second_arg_force_ref, 0) + ZEND_ARG_PASS_INFO(0) + ZEND_ARG_PASS_INFO(1) + ZEND_END_ARG_INFO(); + +ZEND_API + ZEND_BEGIN_ARG_INFO(third_arg_force_ref, 0) + ZEND_ARG_PASS_INFO(0) + ZEND_ARG_PASS_INFO(0) + ZEND_ARG_PASS_INFO(1) + ZEND_END_ARG_INFO(); + + +ZEND_API + ZEND_BEGIN_ARG_INFO(fourth_arg_force_ref, 0) + ZEND_ARG_PASS_INFO(0) + ZEND_ARG_PASS_INFO(0) + ZEND_ARG_PASS_INFO(0) + ZEND_ARG_PASS_INFO(1) + ZEND_END_ARG_INFO(); static zend_function_entry builtin_functions[] = { ZEND_FE(zend_version, NULL) @@ -1712,6 +1736,7 @@ ZEND_FUNCTION(get_extension_funcs) } /* }}} */ + /* * Local variables: * tab-width: 4 diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index a4e212a973..4ff5de2ef9 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -930,7 +930,6 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n init_op_array(&op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE TSRMLS_CC); op_array.function_name = name; - op_array.arg_types = NULL; op_array.return_reference = return_reference; op_array.fn_flags = fn_flags; @@ -1048,10 +1047,12 @@ void zend_do_end_function_declaration(znode *function_token TSRMLS_DC) } -void zend_do_receive_arg(zend_uchar op, znode *var, znode *offset, znode *initialization, znode *class_type, zend_uchar pass_type TSRMLS_DC) +void zend_do_receive_arg(zend_uchar op, znode *var, znode *offset, znode *initialization, znode *class_type, znode *varname, zend_uchar pass_by_reference TSRMLS_DC) { zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); + zend_arg_info *cur_arg_info; + CG(active_op_array)->num_args++; opline->opcode = op; opline->result = *var; opline->op1 = *offset; @@ -1060,33 +1061,20 @@ void zend_do_receive_arg(zend_uchar op, znode *var, znode *offset, znode *initia } else { SET_UNUSED(opline->op2); } - if (!CG(active_op_array)->arg_types) { - if (pass_type==BYREF_FORCE) { - int i; - - CG(active_op_array)->arg_types = (unsigned char *) emalloc(sizeof(unsigned char)*(offset->u.constant.value.lval+1)); - for (i=1; i<offset->u.constant.value.lval; i++) { - CG(active_op_array)->arg_types[i] = BYREF_NONE; - } - CG(active_op_array)->arg_types[0]=(unsigned char) offset->u.constant.value.lval; - CG(active_op_array)->arg_types[offset->u.constant.value.lval] = pass_type; - } - } else { - CG(active_op_array)->arg_types = (unsigned char *) erealloc(CG(active_op_array)->arg_types, sizeof(unsigned char)*(offset->u.constant.value.lval+1)); - CG(active_op_array)->arg_types[0]=(unsigned char) offset->u.constant.value.lval; - CG(active_op_array)->arg_types[offset->u.constant.value.lval] = pass_type; - } + CG(active_op_array)->arg_info = erealloc(CG(active_op_array)->arg_info, sizeof(zend_arg_info)*(CG(active_op_array)->num_args)); + cur_arg_info = &CG(active_op_array)->arg_info[CG(active_op_array)->num_args-1]; + cur_arg_info->name = estrndup(varname->u.constant.value.str.val, varname->u.constant.value.str.len); + cur_arg_info->name_len = varname->u.constant.value.str.len; + cur_arg_info->allow_null = 1; + cur_arg_info->pass_by_reference = pass_by_reference; if (class_type->op_type != IS_UNUSED) { - znode passed_var = opline->result; - - opline = get_next_op(CG(active_op_array) TSRMLS_CC); - - opline->opcode = ZEND_VERIFY_INSTANCEOF; - opline->op1 = *class_type; - opline->op2 = passed_var; - opline->extended_value = offset->u.constant.value.lval; + cur_arg_info->class_name = class_type->u.constant.value.str.val; + cur_arg_info->class_name_len = class_type->u.constant.value.str.len; + zend_str_tolower(cur_arg_info->class_name, cur_arg_info->class_name_len); } else { + cur_arg_info->class_name = NULL; + cur_arg_info->class_name_len = 0; opline->result.u.EA.type |= EXT_TYPE_UNUSED; } } @@ -1296,12 +1284,10 @@ void zend_do_end_function_call(znode *function_name, znode *result, znode *argum void zend_do_pass_param(znode *param, zend_uchar op, int offset TSRMLS_DC) { zend_op *opline; - unsigned char *arg_types; int original_op=op; zend_function **function_ptr_ptr, *function_ptr; int send_by_reference; - - + zend_stack_top(&CG(function_call_stack), (void **) &function_ptr_ptr); function_ptr = *function_ptr_ptr; @@ -1318,14 +1304,11 @@ void zend_do_pass_param(znode *param, zend_uchar op, int offset TSRMLS_DC) } if (function_ptr) { - arg_types = function_ptr->common.arg_types; + send_by_reference = ARG_SHOULD_BE_SENT_BY_REF(function_ptr, (zend_uint) offset) ? ZEND_ARG_SEND_BY_REF : 0; } else { - arg_types = NULL; + send_by_reference = 0; } - send_by_reference = ARG_SHOULD_BE_SENT_BY_REF(offset, 1, arg_types)?ZEND_ARG_SEND_BY_REF:0; - - if (op == ZEND_SEND_VAR && zend_is_function_or_method_call(param)) { /* Method call */ op = ZEND_SEND_VAR_NO_REF; @@ -1333,7 +1316,7 @@ void zend_do_pass_param(znode *param, zend_uchar op, int offset TSRMLS_DC) op = ZEND_SEND_VAR_NO_REF; } - if (op!=ZEND_SEND_VAR_NO_REF && send_by_reference == ZEND_ARG_SEND_BY_REF) { + if (op!=ZEND_SEND_VAR_NO_REF && send_by_reference==ZEND_ARG_SEND_BY_REF) { /* change to passing by reference */ switch (param->op_type) { case IS_VAR: @@ -1611,63 +1594,26 @@ static void do_inherit_method(zend_function *function) static zend_bool zend_do_perform_implementation_check(zend_function *fe) { - zend_op *op, *proto_op; + zend_uint i; if (!fe->common.prototype) { return 1; } - if ((fe->common.arg_types && !fe->common.prototype->common.arg_types) - || (!fe->common.arg_types && fe->common.prototype->common.arg_types)) { + if (fe->common.num_args != fe->common.prototype->common.num_args + || fe->common.pass_rest_by_reference != fe->common.prototype->common.pass_rest_by_reference) { return 0; } - if (fe->common.arg_types) { - if (fe->common.arg_types[0] != fe->common.prototype->common.arg_types[0]) { + for (i=0; i< fe->common.num_args; i++) { + if (strcmp(fe->common.arg_info[i].class_name, fe->common.prototype->common.arg_info[i].class_name)!=0) { return 0; } - if (memcmp(fe->common.arg_types+1, fe->common.prototype->common.arg_types+1, fe->common.arg_types[0]*sizeof(zend_uchar)) != 0) { + if (fe->common.arg_info[i].pass_by_reference != fe->common.prototype->common.arg_info[i].pass_by_reference) { return 0; } } - - if (fe->common.prototype->type == ZEND_INTERNAL_FUNCTION) { - return 1; /* nothing further we can do here */ - } - - op = fe->op_array.opcodes; - proto_op = fe->common.prototype->op_array.opcodes; - - /* Make sure that the implementation has all of the arguments of the interface */ - while (proto_op->opcode != ZEND_RAISE_ABSTRACT_ERROR) { - if (proto_op->opcode != op->opcode) { - return 0; - } - switch (proto_op->opcode) { - case ZEND_FETCH_CLASS: - if (zend_binary_zval_strcasecmp(&op->op2.u.constant, &proto_op->op2.u.constant)!=0) { - return 0; - } - break; - } - proto_op++; - op++; - } - - /* Make sure that the implementation doesn't receive more arguments than the interface */ - while (1) { - switch (op->opcode) { - case ZEND_FETCH_CLASS: - case ZEND_FETCH_W: - op++; - break; - case ZEND_RECV: - case ZEND_RECV_INIT: - return 0; - default: - return 1; - } - } + return 1; } diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 59e05ea273..8e93dbb90e 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -121,14 +121,25 @@ typedef struct _zend_property_info { } zend_property_info; +typedef struct _zend_arg_info { + char *name; + zend_uint name_len; + char *class_name; + zend_uint class_name_len; + zend_bool allow_null; + zend_bool pass_by_reference; +} zend_arg_info; + struct _zend_op_array { /* Common elements */ zend_uchar type; - zend_uchar *arg_types; char *function_name; zend_class_entry *scope; zend_uint fn_flags; union _zend_function *prototype; + zend_uint num_args; + zend_arg_info *arg_info; + zend_bool pass_rest_by_reference; /* END of common elements */ zend_uint *refcount; @@ -165,11 +176,13 @@ struct _zend_op_array { typedef struct _zend_internal_function { /* Common elements */ zend_uchar type; - zend_uchar *arg_types; char *function_name; zend_class_entry *scope; zend_uint fn_flags; union _zend_function *prototype; + zend_uint num_args; + zend_arg_info *arg_info; + zend_bool pass_rest_by_reference; /* END of common elements */ void (*handler)(INTERNAL_FUNCTION_PARAMETERS); @@ -182,11 +195,13 @@ typedef union _zend_function { struct { zend_uchar type; /* never used */ - zend_uchar *arg_types; char *function_name; zend_class_entry *scope; zend_uint fn_flags; union _zend_function *prototype; + zend_uint num_args; + zend_arg_info *arg_info; + zend_bool pass_rest_by_reference; } common; zend_op_array op_array; @@ -320,7 +335,7 @@ void zend_do_add_variable(znode *result, znode *op1, znode *op2 TSRMLS_DC); int zend_do_verify_access_types(znode *current_access_type, znode *new_modifier); void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference, znode *fn_flags_znode TSRMLS_DC); void zend_do_end_function_declaration(znode *function_token TSRMLS_DC); -void zend_do_receive_arg(zend_uchar op, znode *var, znode *offset, znode *initialization, znode *class_type, zend_uchar pass_type TSRMLS_DC); +void zend_do_receive_arg(zend_uchar op, znode *var, znode *offset, znode *initialization, znode *class_type, znode *varname, zend_bool pass_by_reference TSRMLS_DC); int zend_do_begin_function_call(znode *function_name TSRMLS_DC); void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC); void zend_do_begin_dynamic_function_call(znode *function_name TSRMLS_DC); @@ -653,7 +668,6 @@ int zendlex(znode *zendlval TSRMLS_DC); #define ZEND_ADD_INTERFACE 144 -#define ZEND_VERIFY_INSTANCEOF 145 #define ZEND_VERIFY_ABSTRACT_CLASS 146 #define ZEND_ASSIGN_DIM 147 @@ -751,23 +765,24 @@ int zendlex(znode *zendlval TSRMLS_DC); } /* Lost In Stupid Parentheses */ -#define ARG_SHOULD_BE_SENT_BY_REF(offset, conduct_check, arg_types) \ - ( \ - conduct_check \ - && arg_types \ - && \ - ( \ - ( \ - offset<=arg_types[0] \ - && arg_types[offset]==BYREF_FORCE \ - ) \ - || ( \ - offset>=arg_types[0] \ - && arg_types[arg_types[0]]==BYREF_FORCE_REST \ - ) \ - ) \ +#define ARG_SHOULD_BE_SENT_BY_REF(zf, arg_num) \ + ( \ + zf \ + && ((zend_function *) zf)->common.arg_info \ + && \ + ( \ + ( \ + arg_num<=((zend_function *) zf)->common.num_args \ + && ((zend_function *) zf)->common.arg_info[arg_num-1].pass_by_reference \ + ) \ + || ( \ + arg_num>((zend_function *) zf)->common.num_args \ + && ((zend_function *) zf)->common.pass_rest_by_reference \ + ) \ + ) \ ) + #define ZEND_RETURN_VAL 0 #define ZEND_RETURN_REF 1 diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 5cba52658f..4afc36f267 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -281,6 +281,49 @@ static inline zval *get_obj_zval_ptr(znode *op, temp_variable *Ts, zval **freeop return get_zval_ptr(op, Ts, freeop, type); } + +static inline void zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zval *arg TSRMLS_DC) +{ + zend_arg_info *cur_arg_info; + + if (!zf->common.arg_info + || arg_num>zf->common.num_args) { + return; + } + + cur_arg_info = &zf->common.arg_info[arg_num-1]; + + if (cur_arg_info->class_name) { + if (!arg) { + zend_error(E_ERROR, "Argument %d must be an object of class %s", arg_num, cur_arg_info->class_name); + } + switch (Z_TYPE_P(arg)) { + case IS_NULL: + if (!cur_arg_info->allow_null) { + zend_error(E_ERROR, "Argument %d must not be null", arg_num); + } + break; + case IS_OBJECT: { + zend_class_entry *ce = zend_fetch_class(cur_arg_info->class_name, cur_arg_info->class_name_len, ZEND_FETCH_CLASS_AUTO TSRMLS_CC); + if (!instanceof_function(Z_OBJCE_P(arg), ce TSRMLS_CC)) { + char *error_msg; + + if (ce->ce_flags & ZEND_ACC_INTERFACE) { + error_msg = "implement interface"; + } else { + error_msg = "be an instance of"; + } + zend_error(E_ERROR, "Argument %d must %s %s", arg_num, error_msg, ce->name); + } + } + break; + default: + zend_error(E_ERROR, "Argument %d must be an object of class %s", arg_num, cur_arg_info->class_name); + break; + } + } +} + static inline void zend_assign_to_object(znode *result, zval **object_ptr, znode *op2, znode *value_op, temp_variable *Ts, int opcode TSRMLS_DC) { zval *object; @@ -1784,7 +1827,7 @@ int zend_fetch_rw_handler(ZEND_OPCODE_HANDLER_ARGS) int zend_fetch_func_arg_handler(ZEND_OPCODE_HANDLER_ARGS) { - if (ARG_SHOULD_BE_SENT_BY_REF(EX(opline)->extended_value, EX(fbc), EX(fbc)->common.arg_types)) { + if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), EX(opline)->extended_value)) { /* Behave like FETCH_W */ zend_fetch_var_address(EX(opline), EX(Ts), BP_VAR_W TSRMLS_CC); } else { @@ -1851,7 +1894,7 @@ int zend_fetch_dim_is_handler(ZEND_OPCODE_HANDLER_ARGS) int zend_fetch_dim_func_arg_handler(ZEND_OPCODE_HANDLER_ARGS) { - if (ARG_SHOULD_BE_SENT_BY_REF(EX(opline)->extended_value, EX(fbc), EX(fbc)->common.arg_types)) { + if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), EX(opline)->extended_value)) { /* Behave like FETCH_DIM_W */ zend_fetch_dimension_address(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts), BP_VAR_W TSRMLS_CC); } else { @@ -1912,7 +1955,7 @@ int zend_fetch_obj_is_handler(ZEND_OPCODE_HANDLER_ARGS) int zend_fetch_obj_func_arg_handler(ZEND_OPCODE_HANDLER_ARGS) { - if (ARG_SHOULD_BE_SENT_BY_REF(EX(opline)->extended_value, EX(fbc), EX(fbc)->common.arg_types)) { + if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), EX(opline)->extended_value)) { /* Behave like FETCH_OBJ_W */ zend_fetch_property_address(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts), BP_VAR_W TSRMLS_CC); } else { @@ -2453,6 +2496,19 @@ int zend_do_fcall_common_helper(ZEND_OPCODE_HANDLER_ARGS) ALLOC_ZVAL(EX_T(EX(opline)->result.u.var).var.ptr); INIT_ZVAL(*(EX_T(EX(opline)->result.u.var).var.ptr)); + if (EX(function_state).function->common.arg_info) { + zend_uint i=0; + zval **p; + ulong arg_count; + + p = (zval **) EG(argument_stack).top_element-2; + arg_count = (ulong) *p; + + while (arg_count>0) { + zend_verify_arg_type(EX(function_state).function, ++i, *(p-arg_count) TSRMLS_CC); + arg_count--; + } + } if (!zend_execute_internal) { /* saves one function call if zend_execute_internal is not used */ ((zend_internal_function *) EX(function_state).function)->handler(EX(opline)->extended_value, EX_T(EX(opline)->result.u.var).var.ptr, EX(object), return_value_used TSRMLS_CC); @@ -2702,7 +2758,7 @@ exception_should_be_taken: int zend_send_val_handler(ZEND_OPCODE_HANDLER_ARGS) { if (EX(opline)->extended_value==ZEND_DO_FCALL_BY_NAME - && ARG_SHOULD_BE_SENT_BY_REF(EX(opline)->op2.u.opline_num, EX(fbc), EX(fbc)->common.arg_types)) { + && ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), EX(opline)->op2.u.opline_num)) { zend_error(E_ERROR, "Cannot pass parameter %d by reference", EX(opline)->op2.u.opline_num); } { @@ -2755,7 +2811,7 @@ int zend_send_var_no_ref_handler(ZEND_OPCODE_HANDLER_ARGS) if (!(EX(opline)->extended_value & ZEND_ARG_SEND_BY_REF)) { return zend_send_by_var_helper(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } - } else if (!ARG_SHOULD_BE_SENT_BY_REF(EX(opline)->op2.u.opline_num, EX(fbc), EX(fbc)->common.arg_types)) { + } else if (!ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), EX(opline)->op2.u.opline_num)) { return zend_send_by_var_helper(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } { @@ -2796,7 +2852,7 @@ int zend_send_ref_handler(ZEND_OPCODE_HANDLER_ARGS) int zend_send_var_handler(ZEND_OPCODE_HANDLER_ARGS) { if ((EX(opline)->extended_value == ZEND_DO_FCALL_BY_NAME) - && ARG_SHOULD_BE_SENT_BY_REF(EX(opline)->op2.u.opline_num, EX(fbc), EX(fbc)->common.arg_types)) { + && ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), EX(opline)->op2.u.opline_num)) { return zend_send_ref_handler(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } return zend_send_by_var_helper(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -2806,16 +2862,21 @@ int zend_send_var_handler(ZEND_OPCODE_HANDLER_ARGS) int zend_recv_handler(ZEND_OPCODE_HANDLER_ARGS) { zval **param; + zend_uint arg_num = EX(opline)->op1.u.constant.value.lval; - if (zend_ptr_stack_get_arg(EX(opline)->op1.u.constant.value.lval, (void **) ¶m TSRMLS_CC)==FAILURE) { + if (zend_ptr_stack_get_arg(arg_num, (void **) ¶m TSRMLS_CC)==FAILURE) { + zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, NULL TSRMLS_CC); zend_error(E_WARNING, "Missing argument %d for %s()\n", EX(opline)->op1.u.constant.value.lval, get_active_function_name(TSRMLS_C)); if (EX(opline)->result.op_type == IS_VAR) { PZVAL_UNLOCK(*EX_T(EX(opline)->result.u.var).var.ptr_ptr); } - } else if (PZVAL_IS_REF(*param)) { - zend_assign_to_variable_reference(&EX(opline)->result, get_zval_ptr_ptr(&EX(opline)->result, EX(Ts), BP_VAR_W), param, NULL TSRMLS_CC); } else { - zend_assign_to_variable(&EX(opline)->result, &EX(opline)->result, NULL, *param, IS_VAR, EX(Ts) TSRMLS_CC); + zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, *param TSRMLS_CC); + if (PZVAL_IS_REF(*param)) { + zend_assign_to_variable_reference(&EX(opline)->result, get_zval_ptr_ptr(&EX(opline)->result, EX(Ts), BP_VAR_W), param, NULL TSRMLS_CC); + } else { + zend_assign_to_variable(&EX(opline)->result, &EX(opline)->result, NULL, *param, IS_VAR, EX(Ts) TSRMLS_CC); + } } NEXT_OPCODE(); @@ -2825,8 +2886,9 @@ int zend_recv_handler(ZEND_OPCODE_HANDLER_ARGS) int zend_recv_init_handler(ZEND_OPCODE_HANDLER_ARGS) { zval **param, *assignment_value; + zend_uint arg_num = EX(opline)->op1.u.constant.value.lval; - if (zend_ptr_stack_get_arg(EX(opline)->op1.u.constant.value.lval, (void **) ¶m TSRMLS_CC)==FAILURE) { + if (zend_ptr_stack_get_arg(arg_num, (void **) ¶m TSRMLS_CC)==FAILURE) { if (EX(opline)->op2.u.constant.type == IS_CONSTANT || EX(opline)->op2.u.constant.type==IS_CONSTANT_ARRAY) { zval *default_value; @@ -2845,9 +2907,11 @@ int zend_recv_init_handler(ZEND_OPCODE_HANDLER_ARGS) param = NULL; assignment_value = &EX(opline)->op2.u.constant; } + zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, assignment_value TSRMLS_CC); zend_assign_to_variable(&EX(opline)->result, &EX(opline)->result, NULL, assignment_value, IS_VAR, EX(Ts) TSRMLS_CC); } else { assignment_value = *param; + zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, assignment_value TSRMLS_CC); if (PZVAL_IS_REF(assignment_value)) { zend_assign_to_variable_reference(&EX(opline)->result, get_zval_ptr_ptr(&EX(opline)->result, EX(Ts), BP_VAR_W), param, NULL TSRMLS_CC); } else { @@ -3847,27 +3911,6 @@ int zend_add_interface_handler(ZEND_OPCODE_HANDLER_ARGS) } -int zend_verify_instanceof_handler(ZEND_OPCODE_HANDLER_ARGS) -{ - zval *arg = get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R); - zend_class_entry *ce = EX_T(EX(opline)->op1.u.var).EA.class_entry; - - if ((Z_TYPE_P(arg) != IS_OBJECT) - || !instanceof_function(Z_OBJCE_P(arg), ce TSRMLS_CC)) { - char *error_msg; - - if (ce->ce_flags & ZEND_ACC_INTERFACE) { - error_msg = "implement interface"; - } else { - error_msg = "be an instance of"; - } - zend_error(E_ERROR, "Argument %d must %s %s", EX(opline)->extended_value, error_msg, ce->name); - } - - NEXT_OPCODE(); -} - - #define MAX_ABSTRACT_INFO_CNT 3 #define MAX_ABSTRACT_INFO_FMT "%s%s%s%s" @@ -4075,7 +4118,6 @@ void zend_init_opcodes_handlers() zend_opcode_handlers[ZEND_RAISE_ABSTRACT_ERROR] = zend_raise_abstract_error_handler; zend_opcode_handlers[ZEND_ADD_INTERFACE] = zend_add_interface_handler; - zend_opcode_handlers[ZEND_VERIFY_INSTANCEOF] = zend_verify_instanceof_handler; zend_opcode_handlers[ZEND_VERIFY_ABSTRACT_CLASS] = zend_verify_abstract_class_handler; zend_opcode_handlers[ZEND_ASSIGN_DIM] = zend_assign_dim_handler; diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index d57ac934db..4fd8f06c64 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -459,10 +459,10 @@ ZEND_API int zval_update_constant(zval **pp, void *arg TSRMLS_DC) } -int call_user_function(HashTable *function_table, zval **object_pp, zval *function_name, zval *retval_ptr, int param_count, zval *params[] TSRMLS_DC) +int call_user_function(HashTable *function_table, zval **object_pp, zval *function_name, zval *retval_ptr, zend_uint param_count, zval *params[] TSRMLS_DC) { zval ***params_array = (zval ***) emalloc(sizeof(zval **)*param_count); - int i; + zend_uint i; int ex_retval; zval *local_retval_ptr; @@ -479,16 +479,18 @@ int call_user_function(HashTable *function_table, zval **object_pp, zval *functi return ex_retval; } -int call_user_function_ex(HashTable *function_table, zval **object_pp, zval *function_name, zval **retval_ptr_ptr, int param_count, zval **params[], int no_separation, HashTable *symbol_table TSRMLS_DC) + +int call_user_function_ex(HashTable *function_table, zval **object_pp, zval *function_name, zval **retval_ptr_ptr, zend_uint param_count, zval **params[], int no_separation, HashTable *symbol_table TSRMLS_DC) { zend_function *function_pointer = NULL; return fast_call_user_function(function_table, object_pp, function_name, retval_ptr_ptr, param_count, params, no_separation, symbol_table, &function_pointer TSRMLS_CC); } -int fast_call_user_function(HashTable *function_table, zval **object_pp, zval *function_name, zval **retval_ptr_ptr, int param_count, zval **params[], int no_separation, HashTable *symbol_table, zend_function **function_pointer TSRMLS_DC) + +int fast_call_user_function(HashTable *function_table, zval **object_pp, zval *function_name, zval **retval_ptr_ptr, zend_uint param_count, zval **params[], int no_separation, HashTable *symbol_table, zend_function **function_pointer TSRMLS_DC) { - int i; + zend_uint i; zval **original_return_value; HashTable *calling_symbol_table; zend_function_state *original_function_state_ptr; @@ -611,9 +613,7 @@ int fast_call_user_function(HashTable *function_table, zval **object_pp, zval *f for (i=0; i<param_count; i++) { zval *param; - if (EX(function_state).function->common.arg_types - && i<EX(function_state).function->common.arg_types[0] - && EX(function_state).function->common.arg_types[i+1]==BYREF_FORCE + if (ARG_SHOULD_BE_SENT_BY_REF(EX(function_state).function, i+1) && !PZVAL_IS_REF(*params[i])) { if ((*params[i])->refcount>1) { zval *new_zval; diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index 3e72f0370b..37b2412c8c 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -390,22 +390,22 @@ parameter_list: non_empty_parameter_list: - optional_class_type T_VARIABLE { znode tmp; fetch_simple_variable(&tmp, &$2, 0 TSRMLS_CC); $$.op_type = IS_CONST; $$.u.constant.value.lval=1; $$.u.constant.type=IS_LONG; INIT_PZVAL(&$$.u.constant); zend_do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, &$1, BYREF_NONE TSRMLS_CC); } - | optional_class_type '&' T_VARIABLE { znode tmp; fetch_simple_variable(&tmp, &$3, 0 TSRMLS_CC); $$.op_type = IS_CONST; $$.u.constant.value.lval=1; $$.u.constant.type=IS_LONG; INIT_PZVAL(&$$.u.constant); zend_do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, &$1, BYREF_FORCE TSRMLS_CC); } - | optional_class_type '&' T_VARIABLE '=' static_scalar { znode tmp; fetch_simple_variable(&tmp, &$3, 0 TSRMLS_CC); $$.op_type = IS_CONST; $$.u.constant.value.lval=1; $$.u.constant.type=IS_LONG; INIT_PZVAL(&$$.u.constant); zend_do_receive_arg(ZEND_RECV_INIT, &tmp, &$$, &$5, &$1, BYREF_FORCE TSRMLS_CC); } - | T_CONST optional_class_type T_VARIABLE { znode tmp; fetch_simple_variable(&tmp, &$3, 0 TSRMLS_CC); $$.op_type = IS_CONST; $$.u.constant.value.lval=1; $$.u.constant.type=IS_LONG; INIT_PZVAL(&$$.u.constant); zend_do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, &$2, BYREF_NONE TSRMLS_CC); } - | optional_class_type T_VARIABLE '=' static_scalar { znode tmp; fetch_simple_variable(&tmp, &$2, 0 TSRMLS_CC); $$.op_type = IS_CONST; $$.u.constant.value.lval=1; $$.u.constant.type=IS_LONG; INIT_PZVAL(&$$.u.constant); zend_do_receive_arg(ZEND_RECV_INIT, &tmp, &$$, &$4, &$1, BYREF_NONE TSRMLS_CC); } - | non_empty_parameter_list ',' optional_class_type T_VARIABLE { znode tmp; fetch_simple_variable(&tmp, &$4, 0 TSRMLS_CC); $$=$1; $$.u.constant.value.lval++; zend_do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, &$3, BYREF_NONE TSRMLS_CC); } - | non_empty_parameter_list ',' optional_class_type '&' T_VARIABLE { znode tmp; fetch_simple_variable(&tmp, &$5, 0 TSRMLS_CC); $$=$1; $$.u.constant.value.lval++; zend_do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, &$3, BYREF_FORCE TSRMLS_CC); } - | non_empty_parameter_list ',' optional_class_type '&' T_VARIABLE '=' static_scalar { znode tmp; fetch_simple_variable(&tmp, &$5, 0 TSRMLS_CC); $$=$1; $$.u.constant.value.lval++; zend_do_receive_arg(ZEND_RECV_INIT, &tmp, &$$, &$7, &$3, BYREF_FORCE TSRMLS_CC); } - | non_empty_parameter_list ',' T_CONST optional_class_type T_VARIABLE { znode tmp; fetch_simple_variable(&tmp, &$5, 0 TSRMLS_CC); $$=$1; $$.u.constant.value.lval++; zend_do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, &$4, BYREF_NONE TSRMLS_CC); } - | non_empty_parameter_list ',' optional_class_type T_VARIABLE '=' static_scalar { znode tmp; fetch_simple_variable(&tmp, &$4, 0 TSRMLS_CC); $$=$1; $$.u.constant.value.lval++; zend_do_receive_arg(ZEND_RECV_INIT, &tmp, &$$, &$6, &$3, BYREF_NONE TSRMLS_CC); } + optional_class_type T_VARIABLE { znode tmp; fetch_simple_variable(&tmp, &$2, 0 TSRMLS_CC); $$.op_type = IS_CONST; $$.u.constant.value.lval=1; $$.u.constant.type=IS_LONG; INIT_PZVAL(&$$.u.constant); zend_do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, &$1, &$2, 0 TSRMLS_CC); } + | optional_class_type '&' T_VARIABLE { znode tmp; fetch_simple_variable(&tmp, &$3, 0 TSRMLS_CC); $$.op_type = IS_CONST; $$.u.constant.value.lval=1; $$.u.constant.type=IS_LONG; INIT_PZVAL(&$$.u.constant); zend_do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, &$1, &$3, 1 TSRMLS_CC); } + | optional_class_type '&' T_VARIABLE '=' static_scalar { znode tmp; fetch_simple_variable(&tmp, &$3, 0 TSRMLS_CC); $$.op_type = IS_CONST; $$.u.constant.value.lval=1; $$.u.constant.type=IS_LONG; INIT_PZVAL(&$$.u.constant); zend_do_receive_arg(ZEND_RECV_INIT, &tmp, &$$, &$5, &$1, &$3, 1 TSRMLS_CC); } + | T_CONST optional_class_type T_VARIABLE { znode tmp; fetch_simple_variable(&tmp, &$3, 0 TSRMLS_CC); $$.op_type = IS_CONST; $$.u.constant.value.lval=1; $$.u.constant.type=IS_LONG; INIT_PZVAL(&$$.u.constant); zend_do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, &$2, &$3, 0 TSRMLS_CC); } + | optional_class_type T_VARIABLE '=' static_scalar { znode tmp; fetch_simple_variable(&tmp, &$2, 0 TSRMLS_CC); $$.op_type = IS_CONST; $$.u.constant.value.lval=1; $$.u.constant.type=IS_LONG; INIT_PZVAL(&$$.u.constant); zend_do_receive_arg(ZEND_RECV_INIT, &tmp, &$$, &$4, &$1, &$2, 0 TSRMLS_CC); } + | non_empty_parameter_list ',' optional_class_type T_VARIABLE { znode tmp; fetch_simple_variable(&tmp, &$4, 0 TSRMLS_CC); $$=$1; $$.u.constant.value.lval++; zend_do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, &$3, &$4, 0 TSRMLS_CC); } + | non_empty_parameter_list ',' optional_class_type '&' T_VARIABLE { znode tmp; fetch_simple_variable(&tmp, &$5, 0 TSRMLS_CC); $$=$1; $$.u.constant.value.lval++; zend_do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, &$3, &$5, 1 TSRMLS_CC); } + | non_empty_parameter_list ',' optional_class_type '&' T_VARIABLE '=' static_scalar { znode tmp; fetch_simple_variable(&tmp, &$5, 0 TSRMLS_CC); $$=$1; $$.u.constant.value.lval++; zend_do_receive_arg(ZEND_RECV_INIT, &tmp, &$$, &$7, &$3, &$5, 1 TSRMLS_CC); } + | non_empty_parameter_list ',' T_CONST optional_class_type T_VARIABLE { znode tmp; fetch_simple_variable(&tmp, &$5, 0 TSRMLS_CC); $$=$1; $$.u.constant.value.lval++; zend_do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, &$4, &$5, 0 TSRMLS_CC); } + | non_empty_parameter_list ',' optional_class_type T_VARIABLE '=' static_scalar { znode tmp; fetch_simple_variable(&tmp, &$4, 0 TSRMLS_CC); $$=$1; $$.u.constant.value.lval++; zend_do_receive_arg(ZEND_RECV_INIT, &tmp, &$$, &$6, &$3, &$4, 0 TSRMLS_CC); } ; optional_class_type: /* empty */ { $$.op_type = IS_UNUSED; } - | fully_qualified_class_name { $$ = $1; } + | T_STRING { $$ = $1; } ; diff --git a/Zend/zend_modules.h b/Zend/zend_modules.h index 572f52c315..1d56f1e89a 100644 --- a/Zend/zend_modules.h +++ b/Zend/zend_modules.h @@ -31,9 +31,11 @@ #define ZEND_MODULE_INFO_FUNC_ARGS zend_module_entry *zend_module TSRMLS_DC #define ZEND_MODULE_INFO_FUNC_ARGS_PASSTHRU zend_module TSRMLS_CC -ZEND_API extern unsigned char first_arg_force_ref[]; -ZEND_API extern unsigned char second_arg_force_ref[]; -ZEND_API extern unsigned char third_arg_force_ref[]; +ZEND_API extern struct _zend_arg_info first_arg_force_ref[2]; +ZEND_API extern struct _zend_arg_info second_arg_force_ref[3]; +ZEND_API extern struct _zend_arg_info third_arg_force_ref[4]; +ZEND_API extern struct _zend_arg_info fourth_arg_force_ref[5]; +ZEND_API extern struct _zend_arg_info all_args_by_ref[1]; #define ZEND_MODULE_API_NO 20020429 #ifdef ZTS @@ -65,7 +67,7 @@ struct _zend_module_entry { unsigned char zts; struct _zend_ini_entry *ini_entry; char *name; - zend_function_entry *functions; + struct _zend_function_entry *functions; int (*module_startup_func)(INIT_FUNC_ARGS); int (*module_shutdown_func)(SHUTDOWN_FUNC_ARGS); int (*request_startup_func)(INIT_FUNC_ARGS); diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index a5d913d409..4d1589ace9 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -617,7 +617,8 @@ static union _zend_function *zend_std_get_method(zval *object, char *method_name zend_internal_function *call_user_call = emalloc(sizeof(zend_internal_function)); call_user_call->type = ZEND_INTERNAL_FUNCTION; call_user_call->handler = zend_std_call_user_call; - call_user_call->arg_types = NULL; + call_user_call->arg_info = NULL; + call_user_call->num_args = 0; call_user_call->scope = zobj->ce; call_user_call->fn_flags = 0; call_user_call->function_name = estrndup(method_name, method_len); diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index ea3732f56e..6afead0c7f 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -77,7 +77,8 @@ void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_siz op_array->doc_comment = NULL; op_array->doc_comment_len = 0; - op_array->arg_types = NULL; + op_array->arg_info = NULL; + op_array->num_args = 0; op_array->scope = NULL; @@ -190,6 +191,7 @@ ZEND_API void destroy_op_array(zend_op_array *op_array TSRMLS_DC) { zend_op *opline = op_array->opcodes; zend_op *end = op_array->opcodes+op_array->last; + zend_uint i; if (op_array->static_variables) { zend_hash_destroy(op_array->static_variables); @@ -224,15 +226,19 @@ ZEND_API void destroy_op_array(zend_op_array *op_array TSRMLS_DC) if (op_array->doc_comment) { efree(op_array->doc_comment); } - if (op_array->arg_types) { - efree(op_array->arg_types); - } if (op_array->brk_cont_array) { efree(op_array->brk_cont_array); } if (op_array->done_pass_two) { zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_dtor_handler, op_array TSRMLS_CC); } + if (op_array->arg_info) { + for (i=0; i<op_array->num_args; i++) { + efree(op_array->arg_info[i].name); + efree(op_array->arg_info[i].class_name); + } + efree(op_array->arg_info); + } } diff --git a/Zend/zend_reflection_api.c b/Zend/zend_reflection_api.c index af5286c891..efbadb544f 100644 --- a/Zend/zend_reflection_api.c +++ b/Zend/zend_reflection_api.c @@ -1621,7 +1621,7 @@ ZEND_FUNCTION(reflection_class_getinterfaces) array_init(return_value); if (ce->num_interfaces) { - int i; + zend_uint i; for (i=0; i < ce->num_interfaces; i++) { zval *interface; diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index af5286c891..efbadb544f 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -1621,7 +1621,7 @@ ZEND_FUNCTION(reflection_class_getinterfaces) array_init(return_value); if (ce->num_interfaces) { - int i; + zend_uint i; for (i=0; i < ce->num_interfaces; i++) { zval *interface; |