diff options
author | Igor Wiedler <igor@wiedler.ch> | 2013-08-24 23:53:43 +0200 |
---|---|---|
committer | Igor Wiedler <igor@wiedler.ch> | 2013-08-25 00:02:46 +0200 |
commit | 85d4cfb00ddda70ae2418db283b0f53431ca62a8 (patch) | |
tree | de1c3404499399f7ce277b8172e5e4753a785942 | |
parent | 30f16c354060f730dbc321799613527e5a7ea00e (diff) | |
download | php-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.php | 5 | ||||
-rw-r--r-- | Zend/tests/use_const/includes/foo_php_version.php | 5 | ||||
-rw-r--r-- | Zend/tests/use_const/includes/global_bar.php | 3 | ||||
-rw-r--r-- | Zend/tests/use_const/includes/global_baz.php | 3 | ||||
-rw-r--r-- | Zend/tests/use_const/no_global_fallback.phpt | 10 | ||||
-rw-r--r-- | Zend/tests/use_const/shadow_core.phpt | 16 | ||||
-rw-r--r-- | Zend/tests/use_const/shadow_global.phpt | 7 | ||||
-rw-r--r-- | Zend/tests/use_function/includes/foo_bar.php | 7 | ||||
-rw-r--r-- | Zend/tests/use_function/includes/foo_strlen.php | 7 | ||||
-rw-r--r-- | Zend/tests/use_function/includes/global_bar.php | 5 | ||||
-rw-r--r-- | Zend/tests/use_function/includes/global_baz.php | 4 | ||||
-rw-r--r-- | Zend/tests/use_function/no_global_fallback.phpt | 11 | ||||
-rw-r--r-- | Zend/tests/use_function/shadow_core.phpt | 18 | ||||
-rw-r--r-- | Zend/tests/use_function/shadow_global.phpt | 11 | ||||
-rw-r--r-- | Zend/zend_compile.c | 41 | ||||
-rw-r--r-- | Zend/zend_compile.h | 2 | ||||
-rw-r--r-- | Zend/zend_globals.h | 3 |
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; |