]> granicus.if.org Git - php/commitdiff
Namespace support for name ambiguity between namespace and class name
authorDmitry Stogov <dmitry@php.net>
Fri, 27 Jul 2007 13:41:36 +0000 (13:41 +0000)
committerDmitry Stogov <dmitry@php.net>
Fri, 27 Jul 2007 13:41:36 +0000 (13:41 +0000)
Zend/tests/ns_010.phpt [new file with mode: 0755]
Zend/tests/ns_020.phpt [new file with mode: 0755]
Zend/tests/ns_037.phpt [new file with mode: 0755]
Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_execute_API.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

diff --git a/Zend/tests/ns_010.phpt b/Zend/tests/ns_010.phpt
new file mode 100755 (executable)
index 0000000..b94971e
--- /dev/null
@@ -0,0 +1,40 @@
+--TEST--
+010: Accesing internal namespace class
+--FILE--
+<?php
+namespace X;
+import X as Y;
+class Foo {
+       const C = "const ok\n";
+       function __construct() {
+               echo "class ok\n";
+       }
+       static function bar() {
+               echo "method ok\n";
+       }
+}
+new Foo();
+new X::Foo();
+new Y::Foo();
+new ::X::Foo();
+Foo::bar();
+X::Foo::bar();
+Y::Foo::bar();
+::X::Foo::bar();
+echo Foo::C;
+echo X::Foo::C;
+echo Y::Foo::C;
+echo ::X::Foo::C;
+--EXPECT--
+class ok
+class ok
+class ok
+class ok
+method ok
+method ok
+method ok
+method ok
+const ok
+const ok
+const ok
+const ok
diff --git a/Zend/tests/ns_020.phpt b/Zend/tests/ns_020.phpt
new file mode 100755 (executable)
index 0000000..32325e0
--- /dev/null
@@ -0,0 +1,18 @@
+--TEST--
+020: Accesing internal namespace function
+--FILE--
+<?php
+namespace X;
+import X as Y;
+function foo() {
+       echo __FUNCTION__,"\n";
+}
+foo();
+X::foo();
+Y::foo();
+::X::foo();
+--EXPECT--
+X::foo
+X::foo
+X::foo
+X::foo
diff --git a/Zend/tests/ns_037.phpt b/Zend/tests/ns_037.phpt
new file mode 100755 (executable)
index 0000000..2f660a6
--- /dev/null
@@ -0,0 +1,40 @@
+--TEST--
+037: Name ambiguity (namespace name or namespace's class name)
+--FILE--
+<?php
+namespace X;
+import X as Y;
+class X {
+       const C = "const ok\n";
+       function __construct() {
+               echo "class ok\n";
+       }
+       static function bar() {
+               echo "method ok\n";
+       }
+}
+new X();
+new X::X();
+new Y::X();
+new ::X::X();
+X::bar();
+X::X::bar();
+Y::X::bar();
+::X::X::bar();
+echo X::C;
+echo X::X::C;
+echo Y::X::C;
+echo ::X::X::C;
+--EXPECT--
+class ok
+class ok
+class ok
+class ok
+method ok
+method ok
+method ok
+method ok
+const ok
+const ok
+const ok
+const ok
index ef586555f135323193e5db2d80654b71f7b98ea2..99c883e029494792b9cb4de706974e6326c7b79c 100644 (file)
@@ -1642,6 +1642,14 @@ void zend_resolve_class_name(znode *class_name, ulong *fetch_type TSRMLS_DC) /*
                        zval_copy_ctor(&class_name->u.constant);
                } else if (CG(current_namespace)) {
                        zend_class_entry **pce;
+                       unsigned int ns_lcname_len;
+                       zstr ns_lcname = zend_u_str_case_fold(Z_TYPE_P(CG(current_namespace)), Z_UNIVAL_P(CG(current_namespace)), Z_UNILEN_P(CG(current_namespace)), 0, &ns_lcname_len);
+
+                       if (ns_lcname_len == lcname_len &&
+                           memcmp(lcname.v, ns_lcname.v, UG(unicode)?UBYTES(lcname_len):lcname_len) == 0) {
+                               *fetch_type |= ZEND_FETCH_CLASS_RT_NS_NAME;
+                       }
+                       efree(ns_lcname.v);
 
                        if (zend_u_hash_find(CG(class_table), Z_TYPE(class_name->u.constant), lcname, lcname_len+1, (void**)&pce) == SUCCESS &&
                            (*pce)->type == ZEND_INTERNAL_CLASS) {
@@ -1729,7 +1737,7 @@ void zend_do_begin_class_member_function_call(znode *class_name, znode *method_n
        znode class_node;
        unsigned char *ptr = NULL;
        zend_op *opline;
-       ulong fetch_type;
+       ulong fetch_type = 0;
        
        if (method_name->op_type == IS_CONST) {
                zstr lcname;
@@ -1755,10 +1763,8 @@ void zend_do_begin_class_member_function_call(znode *class_name, znode *method_n
                fetch_type = ZEND_FETCH_CLASS_GLOBAL;
                zend_resolve_class_name(class_name, &fetch_type TSRMLS_CC);
                class_node = *class_name;
-               fetch_type |= ZEND_FETCH_CLASS_RT_NS_CHECK;
        } else {
                zend_do_fetch_class(&class_node, class_name TSRMLS_CC);
-               fetch_type = 0;
        }
        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
        opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
index fc0fe81b29ab57ef1e5f489e7217981e40052672..ee0d00f60658484ccd9ea8144c51381f6e5cdcfb 100644 (file)
@@ -634,6 +634,7 @@ int zendlex(znode *zendlval TSRMLS_DC);
 #define ZEND_FETCH_CLASS_FLAGS        0xF0
 #define ZEND_FETCH_CLASS_NO_NORMALIZE 0x10
 #define ZEND_FETCH_CLASS_RT_NS_CHECK  0x20
+#define ZEND_FETCH_CLASS_RT_NS_NAME   0x40
 #define ZEND_FETCH_CLASS_NO_AUTOLOAD  0x80
 
 /* variable parsing type (compile-time) */
index 28d866c244c42d10f1aeae890b725d02cb3b831d..2ee7cdae34cfb6cfffa05afd59c65a7cfc06b44f 100644 (file)
@@ -1653,6 +1653,7 @@ ZEND_API zend_class_entry *zend_u_fetch_class(zend_uchar type, zstr class_name,
        int use_autoload = (fetch_type & ZEND_FETCH_CLASS_NO_AUTOLOAD)  ? 0 : 1;
        int do_normalize = (fetch_type & ZEND_FETCH_CLASS_NO_NORMALIZE) ? 0 : 1;
        int rt_ns_check  = (fetch_type & ZEND_FETCH_CLASS_RT_NS_CHECK)  ? 1 : 0;
+       int rt_ns_name   = (fetch_type & ZEND_FETCH_CLASS_RT_NS_NAME)   ? 1 : 0;
        zstr lcname = class_name;
 
        fetch_type = fetch_type & ~ZEND_FETCH_CLASS_FLAGS;
@@ -1719,7 +1720,7 @@ check_fetch_type:
                                }
                        }
                }
-               if (use_autoload) {
+               if (use_autoload && !rt_ns_name) {
                        if (fetch_type == ZEND_FETCH_CLASS_INTERFACE) {
                                zend_error(E_ERROR, "Interface '%R' not found", type, class_name);
                        } else {
index 7fed3705c9de19a3142985d056fd516cb9d57276..94779a444a13c03f13fdc45869cb0b83c5456ec1 100644 (file)
@@ -1823,10 +1823,42 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUS
                        EX(object) = NULL;
                        ZEND_VM_NEXT_OPCODE();
                }
-               efree(lcname.v);
 
                /* no function found. try a static method in class */           
-               ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
+               ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), (opline->extended_value & ZEND_FETCH_CLASS_RT_NS_NAME) ? (opline->extended_value & ~ZEND_FETCH_CLASS_RT_NS_CHECK) : opline->extended_value TSRMLS_CC);
+               
+               if (!ce) {
+                       if (opline->extended_value & ZEND_FETCH_CLASS_RT_NS_NAME) {
+                               zstr ns;
+
+                               if (UG(unicode) && (ns.u = u_memchr(lcname.u, ':', lcname_len)) && ns.u[1] == ':') {
+                                       ns.u += 2;
+                                       lcname_len -= (ns.u - lcname.u);
+                                       if (zend_u_hash_find(EG(function_table), ZEND_STR_TYPE, ns, lcname_len+1, (void **) &EX(fbc))==SUCCESS) {
+                                               efree(lcname.v);
+                                               EX(object) = NULL;
+                                               ZEND_VM_NEXT_OPCODE();
+                                       }
+                       } else if (!UG(unicode) && (ns.s = memchr(lcname.s, ':', lcname_len)) && ns.s[1] == ':') {
+                                       ns.s += 2;
+                                       lcname_len -= (ns.s - lcname.s);
+                                       if (zend_u_hash_find(EG(function_table), ZEND_STR_TYPE, ns, lcname_len+1, (void **) &EX(fbc))==SUCCESS) {
+                                               efree(lcname.v);
+                                               EX(object) = NULL;
+                                               ZEND_VM_NEXT_OPCODE();
+                                       }
+                               }
+                               if (opline->extended_value & ZEND_FETCH_CLASS_RT_NS_CHECK) {
+                                       ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), ns, lcname_len, opline->extended_value & ~ZEND_FETCH_CLASS_RT_NS_CHECK TSRMLS_CC);
+                               } else {
+                                       zend_error(E_ERROR, "Class '%R' not found", Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant));
+                               }
+                       } else {
+                               zend_error(E_ERROR, "Class '%R' not found", Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant));
+                       }
+               }
+
+               efree(lcname.v);
        } else {
                ce = EX_T(opline->op1.u.var).class_entry;
        }
index c250f474d686d4edcb662b4d81853fe77be7eb18..5cba69dc2b001ce89d7b64bf9db8351e3816cb39 100644 (file)
@@ -2575,10 +2575,42 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HAN
                        EX(object) = NULL;
                        ZEND_VM_NEXT_OPCODE();
                }
-               efree(lcname.v);
 
                /* no function found. try a static method in class */
-               ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
+               ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), (opline->extended_value & ZEND_FETCH_CLASS_RT_NS_NAME) ? (opline->extended_value & ~ZEND_FETCH_CLASS_RT_NS_CHECK) : opline->extended_value TSRMLS_CC);
+
+               if (!ce) {
+                       if (opline->extended_value & ZEND_FETCH_CLASS_RT_NS_NAME) {
+                               zstr ns;
+
+                               if (UG(unicode) && (ns.u = u_memchr(lcname.u, ':', lcname_len)) && ns.u[1] == ':') {
+                                       ns.u += 2;
+                                       lcname_len -= (ns.u - lcname.u);
+                                       if (zend_u_hash_find(EG(function_table), ZEND_STR_TYPE, ns, lcname_len+1, (void **) &EX(fbc))==SUCCESS) {
+                                               efree(lcname.v);
+                                               EX(object) = NULL;
+                                               ZEND_VM_NEXT_OPCODE();
+                                       }
+                       } else if (!UG(unicode) && (ns.s = memchr(lcname.s, ':', lcname_len)) && ns.s[1] == ':') {
+                                       ns.s += 2;
+                                       lcname_len -= (ns.s - lcname.s);
+                                       if (zend_u_hash_find(EG(function_table), ZEND_STR_TYPE, ns, lcname_len+1, (void **) &EX(fbc))==SUCCESS) {
+                                               efree(lcname.v);
+                                               EX(object) = NULL;
+                                               ZEND_VM_NEXT_OPCODE();
+                                       }
+                               }
+                               if (opline->extended_value & ZEND_FETCH_CLASS_RT_NS_CHECK) {
+                                       ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), ns, lcname_len, opline->extended_value & ~ZEND_FETCH_CLASS_RT_NS_CHECK TSRMLS_CC);
+                               } else {
+                                       zend_error(E_ERROR, "Class '%R' not found", Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant));
+                               }
+                       } else {
+                               zend_error(E_ERROR, "Class '%R' not found", Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant));
+                       }
+               }
+
+               efree(lcname.v);
        } else {
                ce = EX_T(opline->op1.u.var).class_entry;
        }
@@ -3039,10 +3071,42 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDL
                        EX(object) = NULL;
                        ZEND_VM_NEXT_OPCODE();
                }
-               efree(lcname.v);
 
                /* no function found. try a static method in class */
-               ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
+               ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), (opline->extended_value & ZEND_FETCH_CLASS_RT_NS_NAME) ? (opline->extended_value & ~ZEND_FETCH_CLASS_RT_NS_CHECK) : opline->extended_value TSRMLS_CC);
+
+               if (!ce) {
+                       if (opline->extended_value & ZEND_FETCH_CLASS_RT_NS_NAME) {
+                               zstr ns;
+
+                               if (UG(unicode) && (ns.u = u_memchr(lcname.u, ':', lcname_len)) && ns.u[1] == ':') {
+                                       ns.u += 2;
+                                       lcname_len -= (ns.u - lcname.u);
+                                       if (zend_u_hash_find(EG(function_table), ZEND_STR_TYPE, ns, lcname_len+1, (void **) &EX(fbc))==SUCCESS) {
+                                               efree(lcname.v);
+                                               EX(object) = NULL;
+                                               ZEND_VM_NEXT_OPCODE();
+                                       }
+                       } else if (!UG(unicode) && (ns.s = memchr(lcname.s, ':', lcname_len)) && ns.s[1] == ':') {
+                                       ns.s += 2;
+                                       lcname_len -= (ns.s - lcname.s);
+                                       if (zend_u_hash_find(EG(function_table), ZEND_STR_TYPE, ns, lcname_len+1, (void **) &EX(fbc))==SUCCESS) {
+                                               efree(lcname.v);
+                                               EX(object) = NULL;
+                                               ZEND_VM_NEXT_OPCODE();
+                                       }
+                               }
+                               if (opline->extended_value & ZEND_FETCH_CLASS_RT_NS_CHECK) {
+                                       ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), ns, lcname_len, opline->extended_value & ~ZEND_FETCH_CLASS_RT_NS_CHECK TSRMLS_CC);
+                               } else {
+                                       zend_error(E_ERROR, "Class '%R' not found", Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant));
+                               }
+                       } else {
+                               zend_error(E_ERROR, "Class '%R' not found", Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant));
+                       }
+               }
+
+               efree(lcname.v);
        } else {
                ce = EX_T(opline->op1.u.var).class_entry;
        }
@@ -3504,10 +3568,42 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDL
                        EX(object) = NULL;
                        ZEND_VM_NEXT_OPCODE();
                }
-               efree(lcname.v);
 
                /* no function found. try a static method in class */
-               ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
+               ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), (opline->extended_value & ZEND_FETCH_CLASS_RT_NS_NAME) ? (opline->extended_value & ~ZEND_FETCH_CLASS_RT_NS_CHECK) : opline->extended_value TSRMLS_CC);
+
+               if (!ce) {
+                       if (opline->extended_value & ZEND_FETCH_CLASS_RT_NS_NAME) {
+                               zstr ns;
+
+                               if (UG(unicode) && (ns.u = u_memchr(lcname.u, ':', lcname_len)) && ns.u[1] == ':') {
+                                       ns.u += 2;
+                                       lcname_len -= (ns.u - lcname.u);
+                                       if (zend_u_hash_find(EG(function_table), ZEND_STR_TYPE, ns, lcname_len+1, (void **) &EX(fbc))==SUCCESS) {
+                                               efree(lcname.v);
+                                               EX(object) = NULL;
+                                               ZEND_VM_NEXT_OPCODE();
+                                       }
+                       } else if (!UG(unicode) && (ns.s = memchr(lcname.s, ':', lcname_len)) && ns.s[1] == ':') {
+                                       ns.s += 2;
+                                       lcname_len -= (ns.s - lcname.s);
+                                       if (zend_u_hash_find(EG(function_table), ZEND_STR_TYPE, ns, lcname_len+1, (void **) &EX(fbc))==SUCCESS) {
+                                               efree(lcname.v);
+                                               EX(object) = NULL;
+                                               ZEND_VM_NEXT_OPCODE();
+                                       }
+                               }
+                               if (opline->extended_value & ZEND_FETCH_CLASS_RT_NS_CHECK) {
+                                       ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), ns, lcname_len, opline->extended_value & ~ZEND_FETCH_CLASS_RT_NS_CHECK TSRMLS_CC);
+                               } else {
+                                       zend_error(E_ERROR, "Class '%R' not found", Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant));
+                               }
+                       } else {
+                               zend_error(E_ERROR, "Class '%R' not found", Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant));
+                       }
+               }
+
+               efree(lcname.v);
        } else {
                ce = EX_T(opline->op1.u.var).class_entry;
        }
@@ -3735,10 +3831,42 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HA
                        EX(object) = NULL;
                        ZEND_VM_NEXT_OPCODE();
                }
-               efree(lcname.v);
 
                /* no function found. try a static method in class */
-               ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
+               ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), (opline->extended_value & ZEND_FETCH_CLASS_RT_NS_NAME) ? (opline->extended_value & ~ZEND_FETCH_CLASS_RT_NS_CHECK) : opline->extended_value TSRMLS_CC);
+
+               if (!ce) {
+                       if (opline->extended_value & ZEND_FETCH_CLASS_RT_NS_NAME) {
+                               zstr ns;
+
+                               if (UG(unicode) && (ns.u = u_memchr(lcname.u, ':', lcname_len)) && ns.u[1] == ':') {
+                                       ns.u += 2;
+                                       lcname_len -= (ns.u - lcname.u);
+                                       if (zend_u_hash_find(EG(function_table), ZEND_STR_TYPE, ns, lcname_len+1, (void **) &EX(fbc))==SUCCESS) {
+                                               efree(lcname.v);
+                                               EX(object) = NULL;
+                                               ZEND_VM_NEXT_OPCODE();
+                                       }
+                       } else if (!UG(unicode) && (ns.s = memchr(lcname.s, ':', lcname_len)) && ns.s[1] == ':') {
+                                       ns.s += 2;
+                                       lcname_len -= (ns.s - lcname.s);
+                                       if (zend_u_hash_find(EG(function_table), ZEND_STR_TYPE, ns, lcname_len+1, (void **) &EX(fbc))==SUCCESS) {
+                                               efree(lcname.v);
+                                               EX(object) = NULL;
+                                               ZEND_VM_NEXT_OPCODE();
+                                       }
+                               }
+                               if (opline->extended_value & ZEND_FETCH_CLASS_RT_NS_CHECK) {
+                                       ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), ns, lcname_len, opline->extended_value & ~ZEND_FETCH_CLASS_RT_NS_CHECK TSRMLS_CC);
+                               } else {
+                                       zend_error(E_ERROR, "Class '%R' not found", Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant));
+                               }
+                       } else {
+                               zend_error(E_ERROR, "Class '%R' not found", Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant));
+                       }
+               }
+
+               efree(lcname.v);
        } else {
                ce = EX_T(opline->op1.u.var).class_entry;
        }
@@ -4168,10 +4296,42 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLE
                        EX(object) = NULL;
                        ZEND_VM_NEXT_OPCODE();
                }
-               efree(lcname.v);
 
                /* no function found. try a static method in class */
-               ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
+               ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), (opline->extended_value & ZEND_FETCH_CLASS_RT_NS_NAME) ? (opline->extended_value & ~ZEND_FETCH_CLASS_RT_NS_CHECK) : opline->extended_value TSRMLS_CC);
+
+               if (!ce) {
+                       if (opline->extended_value & ZEND_FETCH_CLASS_RT_NS_NAME) {
+                               zstr ns;
+
+                               if (UG(unicode) && (ns.u = u_memchr(lcname.u, ':', lcname_len)) && ns.u[1] == ':') {
+                                       ns.u += 2;
+                                       lcname_len -= (ns.u - lcname.u);
+                                       if (zend_u_hash_find(EG(function_table), ZEND_STR_TYPE, ns, lcname_len+1, (void **) &EX(fbc))==SUCCESS) {
+                                               efree(lcname.v);
+                                               EX(object) = NULL;
+                                               ZEND_VM_NEXT_OPCODE();
+                                       }
+                       } else if (!UG(unicode) && (ns.s = memchr(lcname.s, ':', lcname_len)) && ns.s[1] == ':') {
+                                       ns.s += 2;
+                                       lcname_len -= (ns.s - lcname.s);
+                                       if (zend_u_hash_find(EG(function_table), ZEND_STR_TYPE, ns, lcname_len+1, (void **) &EX(fbc))==SUCCESS) {
+                                               efree(lcname.v);
+                                               EX(object) = NULL;
+                                               ZEND_VM_NEXT_OPCODE();
+                                       }
+                               }
+                               if (opline->extended_value & ZEND_FETCH_CLASS_RT_NS_CHECK) {
+                                       ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), ns, lcname_len, opline->extended_value & ~ZEND_FETCH_CLASS_RT_NS_CHECK TSRMLS_CC);
+                               } else {
+                                       zend_error(E_ERROR, "Class '%R' not found", Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant));
+                               }
+                       } else {
+                               zend_error(E_ERROR, "Class '%R' not found", Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant));
+                       }
+               }
+
+               efree(lcname.v);
        } else {
                ce = EX_T(opline->op1.u.var).class_entry;
        }
@@ -10033,10 +10193,42 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDL
                        EX(object) = NULL;
                        ZEND_VM_NEXT_OPCODE();
                }
-               efree(lcname.v);
 
                /* no function found. try a static method in class */
-               ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
+               ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), (opline->extended_value & ZEND_FETCH_CLASS_RT_NS_NAME) ? (opline->extended_value & ~ZEND_FETCH_CLASS_RT_NS_CHECK) : opline->extended_value TSRMLS_CC);
+
+               if (!ce) {
+                       if (opline->extended_value & ZEND_FETCH_CLASS_RT_NS_NAME) {
+                               zstr ns;
+
+                               if (UG(unicode) && (ns.u = u_memchr(lcname.u, ':', lcname_len)) && ns.u[1] == ':') {
+                                       ns.u += 2;
+                                       lcname_len -= (ns.u - lcname.u);
+                                       if (zend_u_hash_find(EG(function_table), ZEND_STR_TYPE, ns, lcname_len+1, (void **) &EX(fbc))==SUCCESS) {
+                                               efree(lcname.v);
+                                               EX(object) = NULL;
+                                               ZEND_VM_NEXT_OPCODE();
+                                       }
+                       } else if (!UG(unicode) && (ns.s = memchr(lcname.s, ':', lcname_len)) && ns.s[1] == ':') {
+                                       ns.s += 2;
+                                       lcname_len -= (ns.s - lcname.s);
+                                       if (zend_u_hash_find(EG(function_table), ZEND_STR_TYPE, ns, lcname_len+1, (void **) &EX(fbc))==SUCCESS) {
+                                               efree(lcname.v);
+                                               EX(object) = NULL;
+                                               ZEND_VM_NEXT_OPCODE();
+                                       }
+                               }
+                               if (opline->extended_value & ZEND_FETCH_CLASS_RT_NS_CHECK) {
+                                       ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), ns, lcname_len, opline->extended_value & ~ZEND_FETCH_CLASS_RT_NS_CHECK TSRMLS_CC);
+                               } else {
+                                       zend_error(E_ERROR, "Class '%R' not found", Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant));
+                               }
+                       } else {
+                               zend_error(E_ERROR, "Class '%R' not found", Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant));
+                       }
+               }
+
+               efree(lcname.v);
        } else {
                ce = EX_T(opline->op1.u.var).class_entry;
        }
@@ -11729,10 +11921,42 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER
                        EX(object) = NULL;
                        ZEND_VM_NEXT_OPCODE();
                }
-               efree(lcname.v);
 
                /* no function found. try a static method in class */
-               ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
+               ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), (opline->extended_value & ZEND_FETCH_CLASS_RT_NS_NAME) ? (opline->extended_value & ~ZEND_FETCH_CLASS_RT_NS_CHECK) : opline->extended_value TSRMLS_CC);
+
+               if (!ce) {
+                       if (opline->extended_value & ZEND_FETCH_CLASS_RT_NS_NAME) {
+                               zstr ns;
+
+                               if (UG(unicode) && (ns.u = u_memchr(lcname.u, ':', lcname_len)) && ns.u[1] == ':') {
+                                       ns.u += 2;
+                                       lcname_len -= (ns.u - lcname.u);
+                                       if (zend_u_hash_find(EG(function_table), ZEND_STR_TYPE, ns, lcname_len+1, (void **) &EX(fbc))==SUCCESS) {
+                                               efree(lcname.v);
+                                               EX(object) = NULL;
+                                               ZEND_VM_NEXT_OPCODE();
+                                       }
+                       } else if (!UG(unicode) && (ns.s = memchr(lcname.s, ':', lcname_len)) && ns.s[1] == ':') {
+                                       ns.s += 2;
+                                       lcname_len -= (ns.s - lcname.s);
+                                       if (zend_u_hash_find(EG(function_table), ZEND_STR_TYPE, ns, lcname_len+1, (void **) &EX(fbc))==SUCCESS) {
+                                               efree(lcname.v);
+                                               EX(object) = NULL;
+                                               ZEND_VM_NEXT_OPCODE();
+                                       }
+                               }
+                               if (opline->extended_value & ZEND_FETCH_CLASS_RT_NS_CHECK) {
+                                       ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), ns, lcname_len, opline->extended_value & ~ZEND_FETCH_CLASS_RT_NS_CHECK TSRMLS_CC);
+                               } else {
+                                       zend_error(E_ERROR, "Class '%R' not found", Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant));
+                               }
+                       } else {
+                               zend_error(E_ERROR, "Class '%R' not found", Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant));
+                       }
+               }
+
+               efree(lcname.v);
        } else {
                ce = EX_T(opline->op1.u.var).class_entry;
        }
@@ -13417,10 +13641,42 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER
                        EX(object) = NULL;
                        ZEND_VM_NEXT_OPCODE();
                }
-               efree(lcname.v);
 
                /* no function found. try a static method in class */
-               ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
+               ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), (opline->extended_value & ZEND_FETCH_CLASS_RT_NS_NAME) ? (opline->extended_value & ~ZEND_FETCH_CLASS_RT_NS_CHECK) : opline->extended_value TSRMLS_CC);
+
+               if (!ce) {
+                       if (opline->extended_value & ZEND_FETCH_CLASS_RT_NS_NAME) {
+                               zstr ns;
+
+                               if (UG(unicode) && (ns.u = u_memchr(lcname.u, ':', lcname_len)) && ns.u[1] == ':') {
+                                       ns.u += 2;
+                                       lcname_len -= (ns.u - lcname.u);
+                                       if (zend_u_hash_find(EG(function_table), ZEND_STR_TYPE, ns, lcname_len+1, (void **) &EX(fbc))==SUCCESS) {
+                                               efree(lcname.v);
+                                               EX(object) = NULL;
+                                               ZEND_VM_NEXT_OPCODE();
+                                       }
+                       } else if (!UG(unicode) && (ns.s = memchr(lcname.s, ':', lcname_len)) && ns.s[1] == ':') {
+                                       ns.s += 2;
+                                       lcname_len -= (ns.s - lcname.s);
+                                       if (zend_u_hash_find(EG(function_table), ZEND_STR_TYPE, ns, lcname_len+1, (void **) &EX(fbc))==SUCCESS) {
+                                               efree(lcname.v);
+                                               EX(object) = NULL;
+                                               ZEND_VM_NEXT_OPCODE();
+                                       }
+                               }
+                               if (opline->extended_value & ZEND_FETCH_CLASS_RT_NS_CHECK) {
+                                       ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), ns, lcname_len, opline->extended_value & ~ZEND_FETCH_CLASS_RT_NS_CHECK TSRMLS_CC);
+                               } else {
+                                       zend_error(E_ERROR, "Class '%R' not found", Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant));
+                               }
+                       } else {
+                               zend_error(E_ERROR, "Class '%R' not found", Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant));
+                       }
+               }
+
+               efree(lcname.v);
        } else {
                ce = EX_T(opline->op1.u.var).class_entry;
        }
@@ -14303,10 +14559,42 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HAND
                        EX(object) = NULL;
                        ZEND_VM_NEXT_OPCODE();
                }
-               efree(lcname.v);
 
                /* no function found. try a static method in class */
-               ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
+               ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), (opline->extended_value & ZEND_FETCH_CLASS_RT_NS_NAME) ? (opline->extended_value & ~ZEND_FETCH_CLASS_RT_NS_CHECK) : opline->extended_value TSRMLS_CC);
+
+               if (!ce) {
+                       if (opline->extended_value & ZEND_FETCH_CLASS_RT_NS_NAME) {
+                               zstr ns;
+
+                               if (UG(unicode) && (ns.u = u_memchr(lcname.u, ':', lcname_len)) && ns.u[1] == ':') {
+                                       ns.u += 2;
+                                       lcname_len -= (ns.u - lcname.u);
+                                       if (zend_u_hash_find(EG(function_table), ZEND_STR_TYPE, ns, lcname_len+1, (void **) &EX(fbc))==SUCCESS) {
+                                               efree(lcname.v);
+                                               EX(object) = NULL;
+                                               ZEND_VM_NEXT_OPCODE();
+                                       }
+                       } else if (!UG(unicode) && (ns.s = memchr(lcname.s, ':', lcname_len)) && ns.s[1] == ':') {
+                                       ns.s += 2;
+                                       lcname_len -= (ns.s - lcname.s);
+                                       if (zend_u_hash_find(EG(function_table), ZEND_STR_TYPE, ns, lcname_len+1, (void **) &EX(fbc))==SUCCESS) {
+                                               efree(lcname.v);
+                                               EX(object) = NULL;
+                                               ZEND_VM_NEXT_OPCODE();
+                                       }
+                               }
+                               if (opline->extended_value & ZEND_FETCH_CLASS_RT_NS_CHECK) {
+                                       ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), ns, lcname_len, opline->extended_value & ~ZEND_FETCH_CLASS_RT_NS_CHECK TSRMLS_CC);
+                               } else {
+                                       zend_error(E_ERROR, "Class '%R' not found", Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant));
+                               }
+                       } else {
+                               zend_error(E_ERROR, "Class '%R' not found", Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant));
+                       }
+               }
+
+               efree(lcname.v);
        } else {
                ce = EX_T(opline->op1.u.var).class_entry;
        }
@@ -15641,10 +15929,42 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_
                        EX(object) = NULL;
                        ZEND_VM_NEXT_OPCODE();
                }
-               efree(lcname.v);
 
                /* no function found. try a static method in class */
-               ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
+               ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), (opline->extended_value & ZEND_FETCH_CLASS_RT_NS_NAME) ? (opline->extended_value & ~ZEND_FETCH_CLASS_RT_NS_CHECK) : opline->extended_value TSRMLS_CC);
+
+               if (!ce) {
+                       if (opline->extended_value & ZEND_FETCH_CLASS_RT_NS_NAME) {
+                               zstr ns;
+
+                               if (UG(unicode) && (ns.u = u_memchr(lcname.u, ':', lcname_len)) && ns.u[1] == ':') {
+                                       ns.u += 2;
+                                       lcname_len -= (ns.u - lcname.u);
+                                       if (zend_u_hash_find(EG(function_table), ZEND_STR_TYPE, ns, lcname_len+1, (void **) &EX(fbc))==SUCCESS) {
+                                               efree(lcname.v);
+                                               EX(object) = NULL;
+                                               ZEND_VM_NEXT_OPCODE();
+                                       }
+                       } else if (!UG(unicode) && (ns.s = memchr(lcname.s, ':', lcname_len)) && ns.s[1] == ':') {
+                                       ns.s += 2;
+                                       lcname_len -= (ns.s - lcname.s);
+                                       if (zend_u_hash_find(EG(function_table), ZEND_STR_TYPE, ns, lcname_len+1, (void **) &EX(fbc))==SUCCESS) {
+                                               efree(lcname.v);
+                                               EX(object) = NULL;
+                                               ZEND_VM_NEXT_OPCODE();
+                                       }
+                               }
+                               if (opline->extended_value & ZEND_FETCH_CLASS_RT_NS_CHECK) {
+                                       ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), ns, lcname_len, opline->extended_value & ~ZEND_FETCH_CLASS_RT_NS_CHECK TSRMLS_CC);
+                               } else {
+                                       zend_error(E_ERROR, "Class '%R' not found", Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant));
+                               }
+                       } else {
+                               zend_error(E_ERROR, "Class '%R' not found", Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant));
+                       }
+               }
+
+               efree(lcname.v);
        } else {
                ce = EX_T(opline->op1.u.var).class_entry;
        }