From: Nikita Popov <nikic@php.net> Date: Sat, 8 Oct 2016 14:56:17 +0000 (+0200) Subject: Fix bug #66773, #66862 X-Git-Tag: php-7.1.0RC4~77^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2a75f5026a47099f585e29c5a9d8a2989dab42af;p=php Fix bug #66773, #66862 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. --- diff --git a/NEWS b/NEWS index 0b4cae7cf6..8117d60f2d 100644 --- 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 index 0000000000..bde94afb03 --- /dev/null +++ b/Zend/tests/use_function/no_conflict_with_classes.phpt @@ -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 index 0000000000..9423995af3 --- /dev/null +++ b/Zend/tests/use_no_file_conflict.phpt @@ -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 index 0000000000..c2739ff64d --- /dev/null +++ b/Zend/tests/use_no_file_conflict_1.inc @@ -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 index 0000000000..badcc85bea --- /dev/null +++ b/Zend/tests/use_no_file_conflict_2.inc @@ -0,0 +1,4 @@ +<?php + +namespace Foo; +use A; diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 53cafcb56d..eb373906eb 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -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);