summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Wiedler <igor@wiedler.ch>2013-08-24 23:53:43 +0200
committerIgor Wiedler <igor@wiedler.ch>2013-08-25 00:02:46 +0200
commit85d4cfb00ddda70ae2418db283b0f53431ca62a8 (patch)
treede1c3404499399f7ce277b8172e5e4753a785942
parent30f16c354060f730dbc321799613527e5a7ea00e (diff)
downloadphp-git-85d4cfb00ddda70ae2418db283b0f53431ca62a8.tar.gz
Disallow using functions/consts defined in the same file
* Keep track of defined function and const filenames * Prohibit use function foo if function foo exists * Prohibit use const foo if const foo exists
-rw-r--r--Zend/tests/use_const/includes/foo_bar.php5
-rw-r--r--Zend/tests/use_const/includes/foo_php_version.php5
-rw-r--r--Zend/tests/use_const/includes/global_bar.php3
-rw-r--r--Zend/tests/use_const/includes/global_baz.php3
-rw-r--r--Zend/tests/use_const/no_global_fallback.phpt10
-rw-r--r--Zend/tests/use_const/shadow_core.phpt16
-rw-r--r--Zend/tests/use_const/shadow_global.phpt7
-rw-r--r--Zend/tests/use_function/includes/foo_bar.php7
-rw-r--r--Zend/tests/use_function/includes/foo_strlen.php7
-rw-r--r--Zend/tests/use_function/includes/global_bar.php5
-rw-r--r--Zend/tests/use_function/includes/global_baz.php4
-rw-r--r--Zend/tests/use_function/no_global_fallback.phpt11
-rw-r--r--Zend/tests/use_function/shadow_core.phpt18
-rw-r--r--Zend/tests/use_function/shadow_global.phpt11
-rw-r--r--Zend/zend_compile.c41
-rw-r--r--Zend/zend_compile.h2
-rw-r--r--Zend/zend_globals.h3
17 files changed, 99 insertions, 59 deletions
diff --git a/Zend/tests/use_const/includes/foo_bar.php b/Zend/tests/use_const/includes/foo_bar.php
new file mode 100644
index 0000000000..90ed451f36
--- /dev/null
+++ b/Zend/tests/use_const/includes/foo_bar.php
@@ -0,0 +1,5 @@
+<?php
+
+namespace foo;
+
+const bar = 'local bar';
diff --git a/Zend/tests/use_const/includes/foo_php_version.php b/Zend/tests/use_const/includes/foo_php_version.php
new file mode 100644
index 0000000000..08f9fd150e
--- /dev/null
+++ b/Zend/tests/use_const/includes/foo_php_version.php
@@ -0,0 +1,5 @@
+<?php
+
+namespace foo;
+
+const PHP_VERSION = 42;
diff --git a/Zend/tests/use_const/includes/global_bar.php b/Zend/tests/use_const/includes/global_bar.php
new file mode 100644
index 0000000000..609d17b7b5
--- /dev/null
+++ b/Zend/tests/use_const/includes/global_bar.php
@@ -0,0 +1,3 @@
+<?php
+
+const bar = 'global bar';
diff --git a/Zend/tests/use_const/includes/global_baz.php b/Zend/tests/use_const/includes/global_baz.php
new file mode 100644
index 0000000000..8b6fba97b3
--- /dev/null
+++ b/Zend/tests/use_const/includes/global_baz.php
@@ -0,0 +1,3 @@
+<?php
+
+const baz = NULL;
diff --git a/Zend/tests/use_const/no_global_fallback.phpt b/Zend/tests/use_const/no_global_fallback.phpt
index fad18797ba..a128f353ed 100644
--- a/Zend/tests/use_const/no_global_fallback.phpt
+++ b/Zend/tests/use_const/no_global_fallback.phpt
@@ -3,14 +3,10 @@ non-existent imported constants should not be looked up in the global table
--FILE--
<?php
-namespace {
- const baz = NULL;
-}
+require 'includes/global_baz.php';
-namespace {
- use const foo\bar\baz;
- var_dump(baz);
-}
+use const foo\bar\baz;
+var_dump(baz);
?>
--EXPECTF--
diff --git a/Zend/tests/use_const/shadow_core.phpt b/Zend/tests/use_const/shadow_core.phpt
index 8052baebc6..7d8bcbd189 100644
--- a/Zend/tests/use_const/shadow_core.phpt
+++ b/Zend/tests/use_const/shadow_core.phpt
@@ -3,22 +3,14 @@ shadowing a global core constant with a local version
--FILE--
<?php
-namespace foo {
- const PHP_VERSION = 42;
-}
+require 'includes/foo_php_version.php';
-namespace {
- var_dump(PHP_VERSION);
-}
+use const foo\PHP_VERSION;
-namespace {
- use const foo\PHP_VERSION;
- var_dump(PHP_VERSION);
- echo "Done\n";
-}
+var_dump(PHP_VERSION);
+echo "Done\n";
?>
--EXPECTF--
-string(%d) "%s"
int(42)
Done
diff --git a/Zend/tests/use_const/shadow_global.phpt b/Zend/tests/use_const/shadow_global.phpt
index ddd47a264c..930cc9f0b8 100644
--- a/Zend/tests/use_const/shadow_global.phpt
+++ b/Zend/tests/use_const/shadow_global.phpt
@@ -4,11 +4,8 @@ shadowing a global constant with a local version
<?php
namespace {
- const bar = 'global bar';
-}
-
-namespace foo {
- const bar = 'local bar';
+ require 'includes/global_bar.php';
+ require 'includes/foo_bar.php';
}
namespace {
diff --git a/Zend/tests/use_function/includes/foo_bar.php b/Zend/tests/use_function/includes/foo_bar.php
new file mode 100644
index 0000000000..6d2f8cab45
--- /dev/null
+++ b/Zend/tests/use_function/includes/foo_bar.php
@@ -0,0 +1,7 @@
+<?php
+
+namespace foo;
+
+function bar() {
+ return 'local bar';
+}
diff --git a/Zend/tests/use_function/includes/foo_strlen.php b/Zend/tests/use_function/includes/foo_strlen.php
new file mode 100644
index 0000000000..d2df2aa2b4
--- /dev/null
+++ b/Zend/tests/use_function/includes/foo_strlen.php
@@ -0,0 +1,7 @@
+<?php
+
+namespace foo;
+
+function strlen($str) {
+ return 4;
+}
diff --git a/Zend/tests/use_function/includes/global_bar.php b/Zend/tests/use_function/includes/global_bar.php
new file mode 100644
index 0000000000..6d7d91f805
--- /dev/null
+++ b/Zend/tests/use_function/includes/global_bar.php
@@ -0,0 +1,5 @@
+<?php
+
+function bar() {
+ return 'global bar';
+}
diff --git a/Zend/tests/use_function/includes/global_baz.php b/Zend/tests/use_function/includes/global_baz.php
new file mode 100644
index 0000000000..6383b9dd38
--- /dev/null
+++ b/Zend/tests/use_function/includes/global_baz.php
@@ -0,0 +1,4 @@
+<?php
+
+function baz() {
+}
diff --git a/Zend/tests/use_function/no_global_fallback.phpt b/Zend/tests/use_function/no_global_fallback.phpt
index 018ae92afc..6597d0d301 100644
--- a/Zend/tests/use_function/no_global_fallback.phpt
+++ b/Zend/tests/use_function/no_global_fallback.phpt
@@ -3,15 +3,10 @@ non-existent imported functions should not be looked up in the global table
--FILE--
<?php
-namespace {
- function baz() {
- }
-}
+require 'includes/global_baz.php';
-namespace {
- use function foo\bar\baz;
- var_dump(baz());
-}
+use function foo\bar\baz;
+var_dump(baz());
?>
--EXPECTF--
diff --git a/Zend/tests/use_function/shadow_core.phpt b/Zend/tests/use_function/shadow_core.phpt
index b06fbfce2e..8f92ff1e1b 100644
--- a/Zend/tests/use_function/shadow_core.phpt
+++ b/Zend/tests/use_function/shadow_core.phpt
@@ -3,24 +3,14 @@ shadowing a global core function with a local version
--FILE--
<?php
-namespace foo {
- function strlen($str) {
- return 4;
- }
-}
+require 'includes/foo_strlen.php';
-namespace {
- var_dump(strlen('foo bar baz'));
-}
+use function foo\strlen;
-namespace {
- use function foo\strlen;
- var_dump(strlen('foo bar baz'));
- echo "Done\n";
-}
+var_dump(strlen('foo bar baz'));
+echo "Done\n";
?>
--EXPECT--
-int(11)
int(4)
Done
diff --git a/Zend/tests/use_function/shadow_global.phpt b/Zend/tests/use_function/shadow_global.phpt
index b3182993b3..791bcdf4d5 100644
--- a/Zend/tests/use_function/shadow_global.phpt
+++ b/Zend/tests/use_function/shadow_global.phpt
@@ -4,15 +4,8 @@ shadowing a global function with a local version
<?php
namespace {
- function bar() {
- return 'global bar';
- }
-}
-
-namespace foo {
- function bar() {
- return 'local bar';
- }
+ require 'includes/global_bar.php';
+ require 'includes/foo_bar.php';
}
namespace {
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 95723c92f1..6770670d31 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -206,6 +206,8 @@ void zend_init_compiler_data_structures(TSRMLS_D) /* {{{ */
CG(current_import) = NULL;
CG(current_import_function) = NULL;
CG(current_import_const) = NULL;
+ zend_hash_init(&CG(function_filenames), 0, NULL, NULL, 0);
+ zend_hash_init(&CG(const_filenames), 0, NULL, NULL, 0);
init_compiler_declarables(TSRMLS_C);
zend_stack_init(&CG(context_stack));
@@ -244,6 +246,8 @@ void shutdown_compiler(TSRMLS_D) /* {{{ */
zend_stack_destroy(&CG(list_stack));
zend_hash_destroy(&CG(filenames_table));
zend_llist_destroy(&CG(open_files));
+ zend_hash_destroy(&CG(function_filenames));
+ zend_hash_destroy(&CG(const_filenames));
zend_stack_destroy(&CG(context_stack));
}
/* }}} */
@@ -1740,6 +1744,7 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
CALCULATE_LITERAL_HASH(opline->op2.constant);
opline->extended_value = ZEND_DECLARE_FUNCTION;
zend_hash_quick_update(CG(function_table), Z_STRVAL(key), Z_STRLEN(key), Z_HASH_P(&CONSTANT(opline->op1.constant)), &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array));
+ zend_hash_add(&CG(function_filenames), lcname, strlen(lcname)+1, CG(compiled_filename), strlen(CG(compiled_filename))+1, NULL);
zend_stack_push(&CG(context_stack), (void *) &CG(context), sizeof(CG(context)));
zend_init_compiler_context(TSRMLS_C);
}
@@ -7147,9 +7152,10 @@ void zend_do_use(znode *ns_name, znode *new_name, int is_global TSRMLS_DC) /* {{
}
/* }}} */
-void zend_do_use_non_class(znode *ns_name, znode *new_name, int is_global, HashTable *current_import_sub TSRMLS_DC) /* {{{ */
+void zend_do_use_non_class(znode *ns_name, znode *new_name, int is_global, const char *type, HashTable *current_import_sub, HashTable *lookup_table TSRMLS_DC) /* {{{ */
{
char *lcname;
+ char *filename;
zval *name, *ns, tmp;
zend_bool warn = 0;
@@ -7182,6 +7188,33 @@ void zend_do_use_non_class(znode *ns_name, znode *new_name, int is_global, HashT
zend_error(E_COMPILE_ERROR, "Cannot use %s as %s because '%s' is a special class name", Z_STRVAL_P(ns), Z_STRVAL_P(name), Z_STRVAL_P(name));
}
+ if (CG(current_namespace)) {
+ /* Prefix import name with current namespace name to avoid conflicts with classes */
+ char *c_ns_name = emalloc(Z_STRLEN_P(CG(current_namespace)) + 1 + Z_STRLEN_P(name) + 1);
+
+ zend_str_tolower_copy(c_ns_name, Z_STRVAL_P(CG(current_namespace)), Z_STRLEN_P(CG(current_namespace)));
+ c_ns_name[Z_STRLEN_P(CG(current_namespace))] = '\\';
+ memcpy(c_ns_name+Z_STRLEN_P(CG(current_namespace))+1, lcname, Z_STRLEN_P(name)+1);
+ if (zend_hash_exists(lookup_table, c_ns_name, Z_STRLEN_P(CG(current_namespace)) + 1 + Z_STRLEN_P(name)+1)) {
+ char *tmp2 = zend_str_tolower_dup(Z_STRVAL_P(ns), Z_STRLEN_P(ns));
+
+ if (Z_STRLEN_P(ns) != Z_STRLEN_P(CG(current_namespace)) + 1 + Z_STRLEN_P(name) ||
+ memcmp(tmp2, c_ns_name, Z_STRLEN_P(ns))) {
+ zend_error(E_COMPILE_ERROR, "Cannot use %s %s as %s because the name is already in use", type, Z_STRVAL_P(ns), Z_STRVAL_P(name));
+ }
+ efree(tmp2);
+ }
+ efree(c_ns_name);
+ } else if (zend_hash_find(lookup_table, lcname, Z_STRLEN_P(name)+1, (void **)&filename) == SUCCESS && strcmp(filename, CG(compiled_filename)) == 0) {
+ char *c_tmp = zend_str_tolower_dup(Z_STRVAL_P(ns), Z_STRLEN_P(ns));
+
+ if (Z_STRLEN_P(ns) != Z_STRLEN_P(name) ||
+ memcmp(c_tmp, lcname, Z_STRLEN_P(ns))) {
+ zend_error(E_COMPILE_ERROR, "Cannot use %s %s as %s because the name is already in use", type, Z_STRVAL_P(ns), Z_STRVAL_P(name));
+ }
+ efree(c_tmp);
+ }
+
if (zend_hash_add(current_import_sub, lcname, Z_STRLEN_P(name)+1, &ns, sizeof(zval*), NULL) != SUCCESS) {
zend_error(E_COMPILE_ERROR, "Cannot use %s as %s because the name is already in use", Z_STRVAL_P(ns), Z_STRVAL_P(name));
}
@@ -7200,7 +7233,7 @@ void zend_do_use_function(znode *ns_name, znode *new_name, int is_global TSRMLS_
zend_hash_init(CG(current_import_function), 0, NULL, ZVAL_PTR_DTOR, 0);
}
- zend_do_use_non_class(ns_name, new_name, is_global, CG(current_import_function) TSRMLS_CC);
+ zend_do_use_non_class(ns_name, new_name, is_global, "function", CG(current_import_function), &CG(function_filenames) TSRMLS_CC);
}
/* }}} */
@@ -7211,7 +7244,7 @@ void zend_do_use_const(znode *ns_name, znode *new_name, int is_global TSRMLS_DC)
zend_hash_init(CG(current_import_const), 0, NULL, ZVAL_PTR_DTOR, 0);
}
- zend_do_use_non_class(ns_name, new_name, is_global, CG(current_import_const) TSRMLS_CC);
+ zend_do_use_non_class(ns_name, new_name, is_global, "const", CG(current_import_const), &CG(const_filenames) TSRMLS_CC);
}
/* }}} */
@@ -7243,6 +7276,8 @@ void zend_do_declare_constant(znode *name, znode *value TSRMLS_DC) /* {{{ */
SET_UNUSED(opline->result);
SET_NODE(opline->op1, name);
SET_NODE(opline->op2, value);
+
+ zend_hash_add(&CG(const_filenames), Z_STRVAL(name->u.constant), Z_STRLEN(name->u.constant)+1, CG(compiled_filename), strlen(CG(compiled_filename))+1, NULL);
}
/* }}} */
diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h
index 3c944e45a6..8145b1cc9b 100644
--- a/Zend/zend_compile.h
+++ b/Zend/zend_compile.h
@@ -638,7 +638,7 @@ void zend_do_begin_namespace(const znode *name, zend_bool with_brackets TSRMLS_D
void zend_do_end_namespace(TSRMLS_D);
void zend_verify_namespace(TSRMLS_D);
void zend_do_use(znode *name, znode *new_name, int is_global TSRMLS_DC);
-void zend_do_use_non_class(znode *ns_name, znode *new_name, int is_global, HashTable *current_import_sub TSRMLS_DC);
+void zend_do_use_non_class(znode *ns_name, znode *new_name, int is_global, const char *type, HashTable *current_import_sub, HashTable *lookup_table TSRMLS_DC);
void zend_do_use_function(znode *name, znode *new_name, int is_global TSRMLS_DC);
void zend_do_use_const(znode *name, znode *new_name, int is_global TSRMLS_DC);
void zend_do_end_compilation(TSRMLS_D);
diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h
index ddb5fc5df7..19c29c68f3 100644
--- a/Zend/zend_globals.h
+++ b/Zend/zend_globals.h
@@ -136,6 +136,9 @@ struct _zend_compiler_globals {
zend_bool in_namespace;
zend_bool has_bracketed_namespaces;
+ HashTable function_filenames;
+ HashTable const_filenames;
+
zend_compiler_context context;
zend_stack context_stack;