]> granicus.if.org Git - php/commitdiff
Fix bug #66773, #66862
authorNikita Popov <nikic@php.net>
Sat, 8 Oct 2016 14:56:17 +0000 (16:56 +0200)
committerNikita Popov <nikic@php.net>
Sat, 8 Oct 2016 15:00:27 +0000 (17:00 +0200)
This a partial backport of 8754b19. It
a) fixes the class/function/constant import table confusion in the
   namespaced case, and
b) restricts conflict checks to a single file based on a filename
   pointer comparison.

It does not fix the issues with filename reuse (e.g. due to eval)
and late-bound classes. This part of the change requires globals
changes.

NEWS
Zend/tests/use_function/no_conflict_with_classes.phpt [new file with mode: 0644]
Zend/tests/use_no_file_conflict.phpt [new file with mode: 0644]
Zend/tests/use_no_file_conflict_1.inc [new file with mode: 0644]
Zend/tests/use_no_file_conflict_2.inc [new file with mode: 0644]
Zend/zend_compile.c

diff --git a/NEWS b/NEWS
index 0b4cae7cf69b404449ee2cb30840ed1b9985fde9..8117d60f2dea8ffcc09cec04d65ded599126bb5f 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,9 @@ PHP                                                                        NEWS
 - Core:
   . Fixed bug #73181 (parse_str() without a second argument leads to crash).
     (Nikita)
+  . Fixed bug #66773 (Autoload with Opcache allows importing conflicting class
+    name to namespace). (Nikita)
+  . Fixed bug #66862 ((Sub-)Namespaces unexpected behaviour). (Nikita)
 
 - GD:
   . Fixed bug #73213 (Integer overflow in imageline() with antialiasing). (cmb)
diff --git a/Zend/tests/use_function/no_conflict_with_classes.phpt b/Zend/tests/use_function/no_conflict_with_classes.phpt
new file mode 100644 (file)
index 0000000..bde94af
--- /dev/null
@@ -0,0 +1,15 @@
+--TEST--
+"use function" should not conflict with class names
+--FILE--
+<?php
+
+namespace Foo;
+
+class Bar {}
+
+use function bar;
+
+?>
+===DONE===
+--EXPECT--
+===DONE===
diff --git a/Zend/tests/use_no_file_conflict.phpt b/Zend/tests/use_no_file_conflict.phpt
new file mode 100644 (file)
index 0000000..9423995
--- /dev/null
@@ -0,0 +1,12 @@
+--TEST--
+Use conflicts should not occur across files
+--FILE--
+<?php
+
+require __DIR__ . '/use_no_file_conflict_1.inc';
+require __DIR__ . '/use_no_file_conflict_2.inc';
+
+?>
+===DONE===
+--EXPECT--
+===DONE===
diff --git a/Zend/tests/use_no_file_conflict_1.inc b/Zend/tests/use_no_file_conflict_1.inc
new file mode 100644 (file)
index 0000000..c2739ff
--- /dev/null
@@ -0,0 +1,4 @@
+<?php
+
+namespace Foo;
+class A {}
diff --git a/Zend/tests/use_no_file_conflict_2.inc b/Zend/tests/use_no_file_conflict_2.inc
new file mode 100644 (file)
index 0000000..badcc85
--- /dev/null
@@ -0,0 +1,4 @@
+<?php
+
+namespace Foo;
+use A;
index 53cafcb56d4f09a6b7fbc303a7af149ba8ffe130..eb373906eb51c625721be39683eda9193bc774f9 100644 (file)
@@ -5499,6 +5499,41 @@ static void zend_check_already_in_use(uint32_t type, zend_string *old_name, zend
 }
 /* }}} */
 
+static void zend_check_use_conflict(
+               uint32_t type, zend_string *old_name, zend_string *new_name, zend_string *lookup_name) {
+       switch (type) {
+               case T_CLASS:
+               {
+                       zend_class_entry *ce = zend_hash_find_ptr(CG(class_table), lookup_name);
+                       if (ce && ce->type == ZEND_USER_CLASS
+                               && ce->info.user.filename == CG(compiled_filename)
+                       ) {
+                               zend_check_already_in_use(type, old_name, new_name, lookup_name);
+                       }
+                       break;
+               }
+               case T_FUNCTION:
+               {
+                       zend_function *fn = zend_hash_find_ptr(CG(function_table), lookup_name);
+                       if (fn && fn->type == ZEND_USER_FUNCTION
+                               && fn->op_array.filename == CG(compiled_filename)
+                       ) {
+                               zend_check_already_in_use(type, old_name, new_name, lookup_name);
+                       }
+                       break;
+               }
+               case T_CONST:
+               {
+                       zend_string *filename = zend_hash_find_ptr(&CG(const_filenames), lookup_name);
+                       if (filename && filename == CG(compiled_filename)) {
+                               zend_check_already_in_use(type, old_name, new_name, lookup_name);
+                       }
+                       break;
+               }
+               EMPTY_SWITCH_DEFAULT_CASE()
+       }
+}
+
 void zend_compile_use(zend_ast *ast) /* {{{ */
 {
        zend_ast_list *list = zend_ast_get_list(ast);
@@ -5555,43 +5590,11 @@ void zend_compile_use(zend_ast *ast) /* {{{ */
                        ZSTR_VAL(ns_name)[ZSTR_LEN(current_ns)] = '\\';
                        memcpy(ZSTR_VAL(ns_name) + ZSTR_LEN(current_ns) + 1, ZSTR_VAL(lookup_name), ZSTR_LEN(lookup_name));
 
-                       if (zend_hash_exists(CG(class_table), ns_name)) {
-                               zend_check_already_in_use(type, old_name, new_name, ns_name);
-                       }
+                       zend_check_use_conflict(type, old_name, new_name, ns_name);
 
                        zend_string_free(ns_name);
                } else {
-                       switch (type) {
-                               case T_CLASS:
-                               {
-                                       zend_class_entry *ce = zend_hash_find_ptr(CG(class_table), lookup_name);
-                                       if (ce && ce->type == ZEND_USER_CLASS
-                                               && ce->info.user.filename == CG(compiled_filename)
-                                       ) {
-                                               zend_check_already_in_use(type, old_name, new_name, lookup_name);
-                                       }
-                                       break;
-                               }
-                               case T_FUNCTION:
-                               {
-                                       zend_function *fn = zend_hash_find_ptr(CG(function_table), lookup_name);
-                                       if (fn && fn->type == ZEND_USER_FUNCTION
-                                               && fn->op_array.filename == CG(compiled_filename)
-                                       ) {
-                                               zend_check_already_in_use(type, old_name, new_name, lookup_name);
-                                       }
-                                       break;
-                               }
-                               case T_CONST:
-                               {
-                                       zend_string *filename = zend_hash_find_ptr(&CG(const_filenames), lookup_name);
-                                       if (filename && filename == CG(compiled_filename)) {
-                                               zend_check_already_in_use(type, old_name, new_name, lookup_name);
-                                       }
-                                       break;
-                               }
-                               EMPTY_SWITCH_DEFAULT_CASE()
-                       }
+                       zend_check_use_conflict(type, old_name, new_name, lookup_name);
                }
 
                zend_string_addref(old_name);