summaryrefslogtreecommitdiff
path: root/Zend
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2020-09-21 12:37:44 +0200
committerNikita Popov <nikita.ppv@gmail.com>2020-09-21 12:37:44 +0200
commitc5f93d191e2bf5a9def069cf9701b5eb6e297a74 (patch)
tree7d0f822aacc7344e492f7007e7aeb1386c908e57 /Zend
parentef9ab9159b409c6d3ea184b4ba88764d85c4133b (diff)
downloadphp-git-c5f93d191e2bf5a9def069cf9701b5eb6e297a74.tar.gz
Fix detection of code outside namespace
Due to improvements to early binding, the opcode based check is no longer accurate. Reuse the syntactic check we're already using for declares instead.
Diffstat (limited to 'Zend')
-rw-r--r--Zend/tests/attributes/004_name_resolution.phpt13
-rw-r--r--Zend/tests/function_outside_namespace.phpt12
-rw-r--r--Zend/tests/type_declarations/confusable_type_warning.phpt10
-rw-r--r--Zend/zend_compile.c30
4 files changed, 36 insertions, 29 deletions
diff --git a/Zend/tests/attributes/004_name_resolution.phpt b/Zend/tests/attributes/004_name_resolution.phpt
index 6f266908b5..aececca0d4 100644
--- a/Zend/tests/attributes/004_name_resolution.phpt
+++ b/Zend/tests/attributes/004_name_resolution.phpt
@@ -2,12 +2,15 @@
Resolve attribute names
--FILE--
<?php
-function dump_attributes($attributes) {
- $arr = [];
- foreach ($attributes as $attribute) {
- $arr[] = ['name' => $attribute->getName(), 'args' => $attribute->getArguments()];
+
+namespace {
+ function dump_attributes($attributes) {
+ $arr = [];
+ foreach ($attributes as $attribute) {
+ $arr[] = ['name' => $attribute->getName(), 'args' => $attribute->getArguments()];
+ }
+ var_dump($arr);
}
- var_dump($arr);
}
namespace Doctrine\ORM\Mapping {
diff --git a/Zend/tests/function_outside_namespace.phpt b/Zend/tests/function_outside_namespace.phpt
new file mode 100644
index 0000000000..f63fb9f56a
--- /dev/null
+++ b/Zend/tests/function_outside_namespace.phpt
@@ -0,0 +1,12 @@
+--TEST--
+Function declaration should not be allowed before namespace declaration
+--FILE--
+<?php
+
+function foo() {}
+
+namespace Bar;
+
+?>
+--EXPECTF--
+Fatal error: Namespace declaration statement has to be the very first statement or after any declare call in the script in %s on line %d
diff --git a/Zend/tests/type_declarations/confusable_type_warning.phpt b/Zend/tests/type_declarations/confusable_type_warning.phpt
index e0202cee06..44bd173451 100644
--- a/Zend/tests/type_declarations/confusable_type_warning.phpt
+++ b/Zend/tests/type_declarations/confusable_type_warning.phpt
@@ -3,10 +3,12 @@ Warnings for confusable types
--FILE--
<?php
-function test1(integer $x) {}
-function test2(double $x) {}
-function test3(boolean $x) {}
-function test4(resource $x) {}
+namespace {
+ function test1(integer $x) {}
+ function test2(double $x) {}
+ function test3(boolean $x) {}
+ function test4(resource $x) {}
+}
namespace Foo {
use integer as foo;
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index f42542c6b2..ba6790a042 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -5864,20 +5864,19 @@ zend_bool zend_handle_encoding_declaration(zend_ast *ast) /* {{{ */
}
/* }}} */
-static zend_result zend_declare_is_first_statement(zend_ast *ast) /* {{{ */
+/* Check whether this is the first statement, not counting declares. */
+static zend_result zend_is_first_statement(zend_ast *ast) /* {{{ */
{
uint32_t i = 0;
zend_ast_list *file_ast = zend_ast_get_list(CG(ast));
- /* Check to see if this declare is preceded only by declare statements */
while (i < file_ast->children) {
if (file_ast->child[i] == ast) {
return SUCCESS;
} else if (file_ast->child[i] == NULL) {
- /* Empty statements are not allowed prior to a declare */
+ /* Empty statements count as statements. */
return FAILURE;
} else if (file_ast->child[i]->kind != ZEND_AST_DECLARE) {
- /* declares can only be preceded by other declares */
return FAILURE;
}
i++;
@@ -5910,14 +5909,14 @@ void zend_compile_declare(zend_ast *ast) /* {{{ */
zval_ptr_dtor_nogc(&value_zv);
} else if (zend_string_equals_literal_ci(name, "encoding")) {
- if (FAILURE == zend_declare_is_first_statement(ast)) {
+ if (FAILURE == zend_is_first_statement(ast)) {
zend_error_noreturn(E_COMPILE_ERROR, "Encoding declaration pragma must be "
"the very first statement in the script");
}
} else if (zend_string_equals_literal_ci(name, "strict_types")) {
zval value_zv;
- if (FAILURE == zend_declare_is_first_statement(ast)) {
+ if (FAILURE == zend_is_first_statement(ast)) {
zend_error_noreturn(E_COMPILE_ERROR, "strict_types declaration must be "
"the very first statement in the script");
}
@@ -7682,20 +7681,11 @@ void zend_compile_namespace(zend_ast *ast) /* {{{ */
}
}
- if (((!with_bracket && !FC(current_namespace))
- || (with_bracket && !FC(has_bracketed_namespaces))) && CG(active_op_array)->last > 0
- ) {
- /* ignore ZEND_EXT_STMT and ZEND_TICKS */
- uint32_t num = CG(active_op_array)->last;
- while (num > 0 &&
- (CG(active_op_array)->opcodes[num-1].opcode == ZEND_EXT_STMT ||
- CG(active_op_array)->opcodes[num-1].opcode == ZEND_TICKS)) {
- --num;
- }
- if (num > 0) {
- zend_error_noreturn(E_COMPILE_ERROR, "Namespace declaration statement has to be "
- "the very first statement or after any declare call in the script");
- }
+ zend_bool is_first_namespace = (!with_bracket && !FC(current_namespace))
+ || (with_bracket && !FC(has_bracketed_namespaces));
+ if (is_first_namespace && FAILURE == zend_is_first_statement(ast)) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Namespace declaration statement has to be "
+ "the very first statement or after any declare call in the script");
}
if (FC(current_namespace)) {