From: Andi Gutmans Date: Tue, 8 Jun 1999 18:33:31 +0000 (+0000) Subject: * Fix a by-name call/method call bug X-Git-Tag: BEFORE_REMOVING_GC_STEP1~174 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=04b2c1d422690f25239e9af8ed41df31a158780f;p=php * Fix a by-name call/method call bug * Clean and optimize the whole function call process --- diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 1ba8e444f3..ddc09edbe6 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -682,7 +682,6 @@ void do_receive_arg(int op, znode *var, znode *offset, znode *initialization, un void do_begin_function_call(znode *function_name CLS_DC) { - zend_op *opline ; zend_function *function; zend_str_tolower(function_name->u.constant.value.str.val, function_name->u.constant.value.str.len); @@ -694,8 +693,6 @@ void do_begin_function_call(znode *function_name CLS_DC) return; } - opline = get_next_op(CG(active_op_array) CLS_CC); - switch (function->type) { case ZEND_USER_FUNCTION: { zend_op_array *op_array = (zend_op_array *) function; @@ -710,9 +707,6 @@ void do_begin_function_call(znode *function_name CLS_DC) } break; } - opline->opcode = ZEND_INIT_FCALL; - SET_UNUSED(opline->op1); - SET_UNUSED(opline->op2); } @@ -756,7 +750,11 @@ void do_end_function_call(znode *function_name, znode *result, znode *argument_l zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); ELS_FETCH(); - opline->opcode = ZEND_DO_FCALL; + if (function_name->op_type==IS_CONST && !is_method) { + opline->opcode = ZEND_DO_FCALL; + } else { + opline->opcode = ZEND_DO_FCALL_BY_NAME; + } opline->op1 = *function_name; opline->result.u.var = get_temporary_variable(CG(active_op_array)); opline->result.op_type = IS_TMP_VAR; @@ -779,8 +777,10 @@ void do_pass_param(znode *param, int op, int offset CLS_DC) function_ptr = *function_ptr_ptr; if (function_ptr) { arg_types = function_ptr->common.arg_types; + opline->extended_value = ZEND_DO_FCALL; } else { arg_types = NULL; + opline->extended_value = ZEND_DO_FCALL_BY_NAME; } if (op == ZEND_SEND_VAL) { @@ -1350,11 +1350,6 @@ void do_shell_exec(znode *result, znode *cmd CLS_DC) { zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); - opline->opcode = ZEND_INIT_FCALL; - SET_UNUSED(opline->op1); - SET_UNUSED(opline->op2); - - opline = get_next_op(CG(active_op_array) CLS_CC); switch (cmd->op_type) { case IS_TMP_VAR: opline->opcode = ZEND_SEND_VAL; @@ -1365,6 +1360,7 @@ void do_shell_exec(znode *result, znode *cmd CLS_DC) } opline->op1 = *cmd; opline->op2.u.opline_num = 0; + opline->extended_value = ZEND_DO_FCALL; SET_UNUSED(opline->op2); opline = get_next_op(CG(active_op_array) CLS_CC); diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 75a3f1ce37..1b704447e6 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -433,9 +433,9 @@ int zendlex(znode *zendlval CLS_DC); #define ZEND_BEGIN_SILENCE 54 #define ZEND_END_SILENCE 55 -#define ZEND_INIT_FCALL 56 -#define ZEND_INIT_FCALL_BY_NAME 57 -#define ZEND_DO_FCALL 58 +#define ZEND_INIT_FCALL_BY_NAME 56 +#define ZEND_DO_FCALL 57 +#define ZEND_DO_FCALL_BY_NAME 58 #define ZEND_RETURN 59 #define ZEND_RECV 60 diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 39dd7be2f4..8b942584a9 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -1247,6 +1247,9 @@ binary_assign_op_addr: { HashTable *active_function_table; zval tmp; + zend_ptr_stack_push(&EG(arg_types_stack), function_being_called); + zend_ptr_stack_push(&EG(arg_types_stack), object_ptr); + if (opline->extended_value & ZEND_CTOR_CALL) { /* constructor call */ EG(AiCount)++; /* for op1 */ @@ -1319,28 +1322,25 @@ binary_assign_op_addr: { zval_dtor(&tmp); function_being_called = function; overloaded_function_call_cont: - zend_ptr_stack_push(&EG(arg_types_stack), function_being_called); FREE_OP(&opline->op2, free_op2); } break; - case ZEND_INIT_FCALL: - object_ptr=NULL; - function_being_called=NULL; - break; + case ZEND_DO_FCALL_BY_NAME: + function_state.function = function_being_called; + goto do_fcall_common; case ZEND_DO_FCALL: { - zval *original_return_value; + zval *fname = get_zval_ptr(&opline->op1, Ts, &free_op1, BP_VAR_R); - if (function_being_called) { - function_being_called = zend_ptr_stack_pop(&EG(arg_types_stack)); - function_state.function = function_being_called; - } else { - zval *fname = get_zval_ptr(&opline->op1, Ts, &free_op1, BP_VAR_R); - - if (zend_hash_find(EG(function_table), fname->value.str.val, fname->value.str.len+1, (void **) &function_state.function)==FAILURE) { - zend_error(E_ERROR, "Unknown function: %s()\n", fname->value.str.val); - } - FREE_OP(&opline->op1, free_op1); + if (zend_hash_find(EG(function_table), fname->value.str.val, fname->value.str.len+1, (void **) &function_state.function)==FAILURE) { + zend_error(E_ERROR, "Unknown function: %s()\n", fname->value.str.val); } + FREE_OP(&opline->op1, free_op1); + goto do_fcall_common; + } +do_fcall_common: + { + zval *original_return_value; + zend_ptr_stack_push(&EG(argument_stack), (void *) opline->extended_value); if (function_state.function->type==ZEND_INTERNAL_FUNCTION) { var_uninit(&Ts[opline->result.u.var].tmp_var); @@ -1356,7 +1356,9 @@ overloaded_function_call_cont: } calling_symbol_table = EG(active_symbol_table); EG(active_symbol_table) = function_state.function_symbol_table; - if (object_ptr && function_being_called && function_being_called->type!=ZEND_OVERLOADED_FUNCTION) { + if (opline->opcode==ZEND_DO_FCALL_BY_NAME + && object_ptr + && function_being_called->type!=ZEND_OVERLOADED_FUNCTION) { zval *dummy = (zval *) emalloc(sizeof(zval)), **this_ptr; var_uninit(dummy); @@ -1386,7 +1388,10 @@ overloaded_function_call_cont: call_overloaded_function(opline->extended_value, &Ts[opline->result.u.var].tmp_var, &EG(regular_list), &EG(persistent_list) ELS_CC); efree(function_being_called); } - function_being_called = NULL; + if (opline->opcode == ZEND_DO_FCALL_BY_NAME) { + object_ptr = zend_ptr_stack_pop(&EG(arg_types_stack)); + function_being_called = zend_ptr_stack_pop(&EG(arg_types_stack)); + } function_state.function = (zend_function *) op_array; EG(function_state_ptr) = &function_state; zend_ptr_stack_clear_multiple(ELS_C); @@ -1409,7 +1414,8 @@ overloaded_function_call_cont: } break; case ZEND_SEND_VAL: - if (function_being_called + if (opline->extended_value==ZEND_DO_FCALL_BY_NAME + && function_being_called && function_being_called->common.arg_types && opline->op2.u.opline_num<=function_being_called->common.arg_types[0] && function_being_called->common.arg_types[opline->op2.u.opline_num]==BYREF_FORCE) { @@ -1426,7 +1432,8 @@ overloaded_function_call_cont: } break; case ZEND_SEND_VAR: - if (function_being_called + if (opline->extended_value==ZEND_DO_FCALL_BY_NAME + && function_being_called && function_being_called->common.arg_types && opline->op2.u.opline_num<=function_being_called->common.arg_types[0] && function_being_called->common.arg_types[opline->op2.u.opline_num]==BYREF_FORCE) {