From: Felipe Pena Date: Wed, 8 Apr 2009 00:28:06 +0000 (+0000) Subject: - Fixed bug #47801 (__call() accessed via parent:: operator is provided incorrect... X-Git-Tag: php-5.2.10RC1~230 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=db53404011e7c07850071cff30314e986cd14ed6;p=php - Fixed bug #47801 (__call() accessed via parent:: operator is provided incorrect method name) --- diff --git a/NEWS b/NEWS index 7d2ee59760..61b408bc2e 100644 --- a/NEWS +++ b/NEWS @@ -19,6 +19,8 @@ PHP NEWS - Fixed bug #47828 (openssl_x509_parse() segfaults when a UTF-8 conversion fails). (Scott, Kees Cook, Pierre) - Fixed bug #47818 (Segfault due to bound callback param). (Felipe) +- Fixed bug #47801 (__call() accessed via parent:: operator is provided + incorrect method name). (Felipe) - Fixed bug #47769 (Strange extends PDO). (Felipe) - Fixed bug #47745 (FILTER_VALIDATE_INT doesn't allow minimum integer). (Dmitry) diff --git a/Zend/tests/bug47801.phpt b/Zend/tests/bug47801.phpt new file mode 100644 index 0000000000..3230819268 --- /dev/null +++ b/Zend/tests/bug47801.phpt @@ -0,0 +1,31 @@ +--TEST-- +Bug #47801 (__call() accessed via parent:: operator is provided incorrect method name) +--FILE-- +getFoo(); + +$b = new B(); +$b->getFoo(); + +?> +--EXPECT-- +magic method called: getFoo +magic method called: getFoo diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 06e29a6906..8cce611e28 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1536,11 +1536,8 @@ void zend_do_begin_class_member_function_call(znode *class_name, znode *method_n memcmp(lcname, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) == 0) { zval_dtor(&opline->op2.u.constant); SET_UNUSED(opline->op2); - efree(lcname); - } else { - efree(opline->op2.u.constant.value.str.val); - opline->op2.u.constant.value.str.val = lcname; } + efree(lcname); } zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *)); diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 288ce987e5..434f1e08f9 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -835,11 +835,8 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS efree(function_name_lc); } } else if (calling_scope) { - char *function_name_lc = zend_str_tolower_dup(fname, fname_len); + EX(function_state).function = zend_std_get_static_method(calling_scope, fname, fname_len TSRMLS_CC); - EX(function_state).function = - zend_std_get_static_method(calling_scope, function_name_lc, fname_len TSRMLS_CC); - efree(function_name_lc); if (check_scope_or_static && EX(function_state).function && !(EX(function_state).function->common.fn_flags & ZEND_ACC_STATIC) && !instanceof_function(check_scope_or_static, calling_scope TSRMLS_CC)) { diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 9fd7db1b80..f1586242c2 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -856,9 +856,14 @@ static union _zend_function *zend_std_get_method(zval **object_ptr, char *method /* This is not (yet?) in the API, but it belongs in the built-in objects callbacks */ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, char *function_name_strval, int function_name_strlen TSRMLS_DC) { - zend_function *fbc; + char *lc_function_name; + zend_function *fbc; + + lc_function_name = zend_str_tolower_dup(function_name_strval, function_name_strlen); + + if (zend_hash_find(&ce->function_table, lc_function_name, function_name_strlen+1, (void **) &fbc)==FAILURE) { + efree(lc_function_name); - if (zend_hash_find(&ce->function_table, function_name_strval, function_name_strlen+1, (void **) &fbc)==FAILURE) { if (ce->__call && EG(This) && Z_OBJ_HT_P(EG(This))->get_class_entry && @@ -886,6 +891,8 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, char *f zend_error(E_ERROR, "Call to undefined method %s::%s()", class_name, function_name_strval); } } + efree(lc_function_name); + if (fbc->op_array.fn_flags & ZEND_ACC_PUBLIC) { /* No further checks necessary, most common case */ } else if (fbc->op_array.fn_flags & ZEND_ACC_PRIVATE) { diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index e00b417659..0febb18da6 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -1795,7 +1795,7 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, ANY, CONST|TMP|VAR|UNUSED|CV) ce = EX_T(opline->op1.u.var).class_entry; if(OP2_TYPE != IS_UNUSED) { - char *function_name_strval; + char *function_name_strval = NULL; int function_name_strlen; zend_bool is_const = (OP2_TYPE == IS_CONST); zend_free_op free_op2; @@ -1808,15 +1808,17 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, ANY, CONST|TMP|VAR|UNUSED|CV) if (Z_TYPE_P(function_name) != IS_STRING) { zend_error_noreturn(E_ERROR, "Function name must be a string"); + } else { + function_name_strval = Z_STRVAL_P(function_name); + function_name_strlen = Z_STRLEN_P(function_name); } - 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; } - EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); + if (function_name_strval) { + EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); + } if (!is_const) { - efree(function_name_strval); FREE_OP2(); } } else { diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 8a7d89917b..f3346d045c 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -667,7 +667,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A ce = EX_T(opline->op1.u.var).class_entry; if(IS_CONST != IS_UNUSED) { - char *function_name_strval; + char *function_name_strval = NULL; int function_name_strlen; zend_bool is_const = (IS_CONST == IS_CONST); @@ -680,15 +680,17 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A if (Z_TYPE_P(function_name) != IS_STRING) { zend_error_noreturn(E_ERROR, "Function name must be a string"); + } else { + function_name_strval = Z_STRVAL_P(function_name); + function_name_strlen = Z_STRLEN_P(function_name); } - 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; } - EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); + if (function_name_strval) { + EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); + } if (!is_const) { - efree(function_name_strval); } } else { @@ -878,7 +880,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG ce = EX_T(opline->op1.u.var).class_entry; if(IS_TMP_VAR != IS_UNUSED) { - char *function_name_strval; + char *function_name_strval = NULL; int function_name_strlen; zend_bool is_const = (IS_TMP_VAR == IS_CONST); zend_free_op free_op2; @@ -891,15 +893,17 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG if (Z_TYPE_P(function_name) != IS_STRING) { zend_error_noreturn(E_ERROR, "Function name must be a string"); + } else { + function_name_strval = Z_STRVAL_P(function_name); + function_name_strlen = Z_STRLEN_P(function_name); } - 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; } - EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); + if (function_name_strval) { + EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); + } if (!is_const) { - efree(function_name_strval); zval_dtor(free_op2.var); } } else { @@ -1049,7 +1053,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG ce = EX_T(opline->op1.u.var).class_entry; if(IS_VAR != IS_UNUSED) { - char *function_name_strval; + char *function_name_strval = NULL; int function_name_strlen; zend_bool is_const = (IS_VAR == IS_CONST); zend_free_op free_op2; @@ -1062,15 +1066,17 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG if (Z_TYPE_P(function_name) != IS_STRING) { zend_error_noreturn(E_ERROR, "Function name must be a string"); + } else { + function_name_strval = Z_STRVAL_P(function_name); + function_name_strlen = Z_STRLEN_P(function_name); } - 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; } - EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); + if (function_name_strval) { + EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); + } if (!is_const) { - efree(function_name_strval); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; } } else { @@ -1219,7 +1225,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ ce = EX_T(opline->op1.u.var).class_entry; if(IS_UNUSED != IS_UNUSED) { - char *function_name_strval; + char *function_name_strval = NULL; int function_name_strlen; zend_bool is_const = (IS_UNUSED == IS_CONST); @@ -1232,15 +1238,17 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ if (Z_TYPE_P(function_name) != IS_STRING) { zend_error_noreturn(E_ERROR, "Function name must be a string"); + } else { + function_name_strval = Z_STRVAL_P(function_name); + function_name_strlen = Z_STRLEN_P(function_name); } - 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; } - EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); + if (function_name_strval) { + EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); + } if (!is_const) { - efree(function_name_strval); } } else { @@ -1322,7 +1330,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS ce = EX_T(opline->op1.u.var).class_entry; if(IS_CV != IS_UNUSED) { - char *function_name_strval; + char *function_name_strval = NULL; int function_name_strlen; zend_bool is_const = (IS_CV == IS_CONST); @@ -1335,15 +1343,17 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS if (Z_TYPE_P(function_name) != IS_STRING) { zend_error_noreturn(E_ERROR, "Function name must be a string"); + } else { + function_name_strval = Z_STRVAL_P(function_name); + function_name_strlen = Z_STRLEN_P(function_name); } - 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; } - EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); + if (function_name_strval) { + EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); + } if (!is_const) { - efree(function_name_strval); } } else {