]> granicus.if.org Git - php/commitdiff
fix #39127i (Old-style constructor fallbacks produce strange results)
authorAntony Dovgal <tony2001@php.net>
Mon, 17 Mar 2008 14:53:43 +0000 (14:53 +0000)
committerAntony Dovgal <tony2001@php.net>
Mon, 17 Mar 2008 14:53:43 +0000 (14:53 +0000)
Zend/tests/bug39127.phpt [new file with mode: 0644]
Zend/zend_compile.c
Zend/zend_object_handlers.c

diff --git a/Zend/tests/bug39127.phpt b/Zend/tests/bug39127.phpt
new file mode 100644 (file)
index 0000000..c05bcd3
--- /dev/null
@@ -0,0 +1,21 @@
+--TEST--
+Bug #39127 (Old-style constructor fallbacks produce strange results)
+--FILE--
+<?php
+
+class a { function a() { var_dump("a::a() called"); } } 
+class b extends a {} 
+
+$b = new b; 
+var_dump(is_callable(array($b,"a")));
+var_dump(is_callable(array($b,"b")));
+var_dump(is_callable(array($b,"__construct")));
+
+echo "Done\n";
+?>
+--EXPECTF--    
+%s(13) "a::a() called"
+bool(true)
+bool(false)
+bool(false)
+Done
index b19194b62ab4443d27d2bcdd0e6e18e1453fae81..ffaf67a73a08de84f629acb2df54fe37392806ed 100644 (file)
@@ -2417,12 +2417,19 @@ static void do_inherit_parent_constructor(zend_class_entry *ce TSRMLS_DC) /* {{{
        } else if (ce->parent->constructor) {
                ce->constructor = ce->parent->constructor;
                if (!zend_ascii_hash_exists(&ce->function_table, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME))) {
-                       unsigned int lc_class_name_len;
-                       zstr lc_class_name = zend_u_str_case_fold(ZEND_STR_TYPE, ce->name, ce->name_length, 0, &lc_class_name_len);
-
-                       zend_u_hash_update(&ce->function_table, ZEND_STR_TYPE, lc_class_name, lc_class_name_len+1, ce->constructor, sizeof(zend_function), NULL);
-                       function_add_ref(ce->constructor TSRMLS_CC);
-                       efree(lc_class_name.v);
+                       unsigned int lc_parent_class_name_len;
+                       zend_function *function;
+                       zstr lc_parent_class_name = zend_u_str_case_fold(ZEND_STR_TYPE, ce->parent->name, ce->parent->name_length, 0, &lc_parent_class_name_len);
+
+                       if (!zend_u_hash_exists(&ce->function_table, ZEND_STR_TYPE, lc_parent_class_name, ce->parent->name_length+1) &&
+                                       zend_u_hash_find(&ce->parent->function_table, ZEND_STR_TYPE, lc_parent_class_name, ce->parent->name_length+1, (void **)&function)==SUCCESS) {
+                               if (function->common.fn_flags & ZEND_ACC_CTOR) {
+                                       /* inherit parent's constructor */
+                                       zend_u_hash_update(&ce->function_table, ZEND_STR_TYPE, lc_parent_class_name, ce->parent->name_length+1, function, sizeof(zend_function), NULL);
+                                       function_add_ref(function);
+                               }
+                       }
+                       efree(lc_parent_class_name.v);
                }
        }
 }
index 09ec4a7fea4b57bd230d7d54c8e261dc1ae2bf9a..04f0a62ea65ddc00a1c68f0b9dd9a51b3940a142 100644 (file)
@@ -905,9 +905,22 @@ ZEND_API void zend_std_callstatic_user_call(INTERNAL_FUNCTION_PARAMETERS) /* {{{
 
 ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_uchar type, zstr function_name_strval, int function_name_strlen TSRMLS_DC) /* {{{ */
 {
-       zend_function *fbc;
+       zend_function *fbc = NULL;
+
+       if (function_name_strlen == ce->name_length && ce->constructor) {
+               zstr lc_class_name;
+               unsigned int lc_class_name_len, real_len;
+
+               lc_class_name = zend_u_str_case_fold(type, ce->name, ce->name_length, 0, &lc_class_name_len);
+               real_len = USTR_BYTES(type, lc_class_name_len);
+
+               if (!memcmp(lc_class_name.s, function_name_strval.s, real_len)) {
+                       fbc = ce->constructor;
+               }
+               efree(lc_class_name.v);
+       }
 
-       if (zend_u_hash_find(&ce->function_table, type, function_name_strval, function_name_strlen + 1, (void **) &fbc)==FAILURE) {
+       if (!fbc && zend_u_hash_find(&ce->function_table, type, function_name_strval, function_name_strlen + 1, (void **) &fbc)==FAILURE) {
                if (ce->__call &&
                    EG(This) &&
                    Z_OBJ_HT_P(EG(This))->get_class_entry &&