From: Zeev Suraski Date: Thu, 9 Oct 2003 13:44:44 +0000 (+0000) Subject: Allow foo::$bar() X-Git-Tag: RELEASE_1_3b3~78 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2ab30d71334ea13757aaeb3ada405789c81523d7;p=php Allow foo::$bar() --- diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 10dc52ccb4..6df8fc3554 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1283,19 +1283,27 @@ void zend_do_begin_class_member_function_call(TSRMLS_D) { unsigned char *ptr = NULL; long fetch_const_op_number = get_next_op_number(CG(active_op_array)); - zend_op *opline = &CG(active_op_array)->opcodes[fetch_const_op_number-1]; - - /* a tmp var is leaked here */ - opline->opcode = ZEND_INIT_STATIC_METHOD_CALL; - if(opline->op2.op_type == IS_CONST && - (sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) == Z_STRLEN(opline->op2.u.constant) && - memcmp(Z_STRVAL(opline->op2.u.constant), ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) == 0) { - zval_dtor(&opline->op2.u.constant); - SET_UNUSED(opline->op2); - } else { - zend_lowercase_znode_if_const(&opline->op2); + zend_op *last_op = &CG(active_op_array)->opcodes[fetch_const_op_number-1]; + + if (last_op->opcode == ZEND_FETCH_CONSTANT) { /* regular method call */ + /* a tmp var is leaked here */ + last_op->opcode = ZEND_INIT_STATIC_METHOD_CALL; + if(last_op->op2.op_type == IS_CONST && + (sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) == Z_STRLEN(last_op->op2.u.constant) && + memcmp(Z_STRVAL(last_op->op2.u.constant), ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) == 0) { + zval_dtor(&last_op->op2.u.constant); + SET_UNUSED(last_op->op2); + } else { + zend_lowercase_znode_if_const(&last_op->op2); + } + } else { /* indirect method call */ + zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); + opline->opcode = ZEND_INIT_STATIC_METHOD_CALL; + opline->op1 = last_op->op2; + opline->op2 = last_op->result; } + zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *)); } diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index a8e20f8cca..3bab0b9cb3 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -2422,7 +2422,10 @@ int zend_init_static_method_call_handler(ZEND_OPCODE_HANDLER_ARGS) function_name_strlen = EX(opline)->op2.u.constant.value.str.len; } else { function_name = get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R); - + + if (Z_TYPE_P(function_name) != IS_STRING) { + zend_error(E_ERROR, "Function name must be a string"); + } function_name_strval = zend_str_tolower_dup(function_name->value.str.val, function_name->value.str.len); function_name_strlen = function_name->value.str.len; } diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index 37b2412c8c..5600e1dff5 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -592,8 +592,11 @@ function_call: function_call_parameter_list ')' { zend_do_end_function_call(&$1, &$$, &$4, 0, $2.u.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); } | class_constant '(' { zend_do_begin_class_member_function_call(TSRMLS_C); zend_do_extended_fcall_begin(TSRMLS_C); } - function_call_parameter_list - ')' { zend_do_end_function_call(NULL, &$$, &$4, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} + function_call_parameter_list + ')' { zend_do_end_function_call(NULL, &$$, &$4, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} + | static_member '(' { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_class_member_function_call(TSRMLS_C); zend_do_extended_fcall_begin(TSRMLS_C); } + function_call_parameter_list + ')' { zend_do_end_function_call(NULL, &$$, &$4, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} | variable_without_objects '(' { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_dynamic_function_call(&$1 TSRMLS_CC); } function_call_parameter_list ')' { zend_do_end_function_call(&$1, &$$, &$4, 0, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}