]> granicus.if.org Git - php/commitdiff
- Fixed bug #47801 (__call() accessed via parent:: operator is provided incorrect...
authorFelipe Pena <felipe@php.net>
Wed, 8 Apr 2009 00:28:06 +0000 (00:28 +0000)
committerFelipe Pena <felipe@php.net>
Wed, 8 Apr 2009 00:28:06 +0000 (00:28 +0000)
NEWS
Zend/tests/bug47801.phpt [new file with mode: 0644]
Zend/zend_compile.c
Zend/zend_execute_API.c
Zend/zend_object_handlers.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

diff --git a/NEWS b/NEWS
index 7d2ee59760ba3285ea4a2c682b701b6c63ba77ff..61b408bc2e6d4116578a0af37ea23a3e268fbde6 100644 (file)
--- 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 (file)
index 0000000..3230819
--- /dev/null
@@ -0,0 +1,31 @@
+--TEST--
+Bug #47801 (__call() accessed via parent:: operator is provided incorrect method name)
+--FILE--
+<?php
+
+class A
+{
+  function __call($name, $args)
+  {
+    echo("magic method called: $name\n");
+  }
+}
+
+class B extends A
+{
+  function getFoo()
+  {
+    parent::getFoo();
+  }
+}
+
+$a = new A();
+$a->getFoo();
+
+$b = new B();
+$b->getFoo();
+
+?>
+--EXPECT--
+magic method called: getFoo
+magic method called: getFoo
index 06e29a6906f040b73681e2db21f9af1a124a8854..8cce611e28195cb2dd8cda8ff5d6e5eeab7ca7a2 100644 (file)
@@ -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 *));
index 288ce987e5a93763486e58e785a67ed33190b3d6..434f1e08f9aedf192be8fd38baad05780550c0d7 100644 (file)
@@ -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)) {
index 9fd7db1b80ab94b90a9809d44464b2b502e7f666..f1586242c20811c53c8e1cd582b4bce8879c2994 100644 (file)
@@ -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) {
index e00b41765923ade1657d1c093d2841605e79549f..0febb18da67a0f00e1af927a66b818a3344ffbb4 100644 (file)
@@ -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 {
index 8a7d89917b5cf7b163026ffd317734f31cd4e8a9..f3346d045c918bfe0eaf673e92dec46656398c9b 100644 (file)
@@ -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 {