[prev in list] [next in list] [prev in thread] [next in thread]
List: php-cvs
Subject: [PHP-CVS] com php-src: Disallow self etc outside classes at compile-time: =?UTF-8?Q?Zend/tests/class
From: Nikita Popov <nikic () php ! net>
Date: 2015-04-29 18:51:08
Message-ID: php-mail-392806c92ac2e3fed1aec60fe5a3e2381031094972 () git ! php ! net
[Download RAW message or body]
Commit: 16a9bc1ec20533c76ba992bfc64dd69e7b7d9001
Author: Nikita Popov <nikic@php.net> Mon, 27 Apr 2015 21:14:58 +0200
Parents: d880ead8a733202be2f74228339390e81ab824b5
Branches: master
Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=16a9bc1ec20533c76ba992bfc64dd69e7b7d9001
Log:
Disallow self etc outside classes at compile-time
Also fix a bug with return types where "self" was rejected inside
a class, but not on a method.
Fallout: A couple of tests changed to more generic error messages.
Changed paths:
M Zend/tests/class_name_as_scalar_error_005.phpt
M Zend/tests/class_name_as_scalar_error_006.phpt
M Zend/tests/class_name_as_scalar_error_007.phpt
M Zend/tests/return_types/024.phpt
M Zend/tests/return_types/025.phpt
M Zend/tests/return_types/026.phpt
M Zend/tests/return_types/027.phpt
M Zend/tests/self_class_const_outside_class.phpt
A Zend/tests/typehints/self_on_closure_in_method.phpt
M Zend/zend_compile.c
["diff_16a9bc1ec20533c76ba992bfc64dd69e7b7d9001.txt" (text/plain)]
diff --git a/Zend/tests/class_name_as_scalar_error_005.phpt \
b/Zend/tests/class_name_as_scalar_error_005.phpt index 39de69f..27700fd 100644
--- a/Zend/tests/class_name_as_scalar_error_005.phpt
+++ b/Zend/tests/class_name_as_scalar_error_005.phpt
@@ -7,4 +7,4 @@ $x = static::class;
?>
--EXPECTF--
-Fatal error: Cannot access static::class when no class scope is active in %s on line \
%d \ No newline at end of file
+Fatal error: Cannot use "static" when no class scope is active in %s on line 3
diff --git a/Zend/tests/class_name_as_scalar_error_006.phpt \
b/Zend/tests/class_name_as_scalar_error_006.phpt index a4cc9a5..a1078d0 100644
--- a/Zend/tests/class_name_as_scalar_error_006.phpt
+++ b/Zend/tests/class_name_as_scalar_error_006.phpt
@@ -7,4 +7,4 @@ $x = parent::class;
?>
--EXPECTF--
-Fatal error: Cannot access parent::class when no class scope is active in %s on line \
%d +Fatal error: Cannot use "parent" when no class scope is active in %s on line 3
diff --git a/Zend/tests/class_name_as_scalar_error_007.phpt \
b/Zend/tests/class_name_as_scalar_error_007.phpt index 2bfa5f3..684470d 100644
--- a/Zend/tests/class_name_as_scalar_error_007.phpt
+++ b/Zend/tests/class_name_as_scalar_error_007.phpt
@@ -7,4 +7,4 @@ var_dump(self::class);
?>
--EXPECTF--
-Fatal error: Cannot access self::class when no class scope is active in %s on line \
%d +Fatal error: Cannot use "self" when no class scope is active in %s on line 3
diff --git a/Zend/tests/return_types/024.phpt b/Zend/tests/return_types/024.phpt
index 9f2691f..0579973 100644
--- a/Zend/tests/return_types/024.phpt
+++ b/Zend/tests/return_types/024.phpt
@@ -7,4 +7,4 @@ Return type of self is not allowed in function
function test(): self {}
--EXPECTF--
-Fatal error: Cannot declare a return type of self outside of a class scope in %s on \
line 3 +Fatal error: Cannot use "self" when no class scope is active in %s on line 3
diff --git a/Zend/tests/return_types/025.phpt b/Zend/tests/return_types/025.phpt
index 650fb08..16a608b 100644
--- a/Zend/tests/return_types/025.phpt
+++ b/Zend/tests/return_types/025.phpt
@@ -7,4 +7,4 @@ Return type of self is not allowed in closure
$c = function(): self {};
--EXPECTF--
-Fatal error: Cannot declare a return type of self outside of a class scope in %s on \
line 3 +Fatal error: Cannot use "self" when no class scope is active in %s on line 3
diff --git a/Zend/tests/return_types/026.phpt b/Zend/tests/return_types/026.phpt
index 44ae82a..5693e95 100644
--- a/Zend/tests/return_types/026.phpt
+++ b/Zend/tests/return_types/026.phpt
@@ -6,4 +6,4 @@ Return type of parent is not allowed in function
function test(): parent {}
--EXPECTF--
-Fatal error: Cannot declare a return type of parent outside of a class scope in %s \
on line 3 +Fatal error: Cannot use "parent" when no class scope is active in %s on \
line %d
diff --git a/Zend/tests/return_types/027.phpt b/Zend/tests/return_types/027.phpt
index 4d615b4..1abc7f7 100644
--- a/Zend/tests/return_types/027.phpt
+++ b/Zend/tests/return_types/027.phpt
@@ -6,4 +6,4 @@ Return type of parent is not allowed in closure
$c = function(): parent {};
--EXPECTF--
-Fatal error: Cannot declare a return type of parent outside of a class scope in %s \
on line 3 +Fatal error: Cannot use "parent" when no class scope is active in %s on \
line 3
diff --git a/Zend/tests/self_class_const_outside_class.phpt \
b/Zend/tests/self_class_const_outside_class.phpt index 0ef03c2..541f3da 100644
--- a/Zend/tests/self_class_const_outside_class.phpt
+++ b/Zend/tests/self_class_const_outside_class.phpt
@@ -5,4 +5,4 @@ Accessing self::FOO outside a class
var_dump(self::FOO);
?>
--EXPECTF--
-Fatal error: Cannot access self:: when no class scope is active in %s on line %d
+Fatal error: Cannot use "self" when no class scope is active in %s on line %d
diff --git a/Zend/tests/typehints/self_on_closure_in_method.phpt \
b/Zend/tests/typehints/self_on_closure_in_method.phpt new file mode 100644
index 0000000..2d5bd82
--- /dev/null
+++ b/Zend/tests/typehints/self_on_closure_in_method.phpt
@@ -0,0 +1,19 @@
+--TEST--
+self return type on closure in a method
+--FILE--
+<?php
+
+class A {
+ public function test() {
+ return function() : self {
+ return $this;
+ };
+ }
+}
+
+var_dump((new A)->test()());
+
+?>
+--EXPECT--
+object(A)#1 (0) {
+}
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index d4a9df3..c92a25a 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -1612,6 +1612,27 @@ uint32_t zend_get_class_fetch_type(zend_string *name) /* {{{ \
*/ }
/* }}} */
+static uint32_t zend_get_class_fetch_type_ast(zend_ast *name_ast) /* {{{ */
+{
+ /* Fully qualified names are always default refs */
+ if (name_ast->attr == ZEND_NAME_FQ) {
+ return ZEND_FETCH_CLASS_DEFAULT;
+ }
+
+ return zend_get_class_fetch_type(zend_ast_get_str(name_ast));
+}
+/* }}} */
+
+void zend_ensure_valid_class_fetch_type(uint32_t fetch_type) /* {{{ */
+{
+ if (fetch_type != ZEND_FETCH_CLASS_DEFAULT && !CG(active_class_entry)) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Cannot use \"%s\" when no class scope is \
active", + fetch_type == ZEND_FETCH_CLASS_SELF ? "self" :
+ fetch_type == ZEND_FETCH_CLASS_PARENT ? "parent" : "static");
+ }
+}
+/* }}} */
+
ZEND_API zend_string *zend_get_compiled_variable_name(const zend_op_array *op_array, \
uint32_t var) /* {{{ */ {
return op_array->vars[EX_VAR_TO_NUM(var)];
@@ -2018,19 +2039,11 @@ static inline zend_bool zend_can_write_to_variable(zend_ast \
*ast) /* {{{ */
static inline zend_bool zend_is_const_default_class_ref(zend_ast *name_ast) /* {{{ \
*/ {
- zend_string *name;
-
if (name_ast->kind != ZEND_AST_ZVAL) {
return 0;
}
- /* Fully qualified names are always default refs */
- if (!name_ast->attr) {
- return 1;
- }
-
- name = zend_ast_get_str(name_ast);
- return ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(name);
+ return ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type_ast(name_ast);
}
/* }}} */
@@ -2077,6 +2090,8 @@ static zend_op *zend_compile_class_ref(znode *result, zend_ast \
*name_ast, int th opline->op2_type = IS_CONST;
opline->op2.constant = zend_add_class_name_literal(CG(active_op_array),
zend_resolve_class_name(name, type));
+ } else {
+ zend_ensure_valid_class_fetch_type(fetch_type);
}
zend_string_release(name);
@@ -4147,7 +4162,7 @@ ZEND_API void zend_set_function_arg_flags(zend_function *func) \
/* {{{ */ }
/* }}} */
-void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, zend_bool \
is_method) /* {{{ */ +void zend_compile_params(zend_ast *ast, zend_ast \
*return_type_ast) /* {{{ */ {
zend_ast_list *list = zend_ast_get_list(ast);
uint32_t i;
@@ -4173,15 +4188,13 @@ void zend_compile_params(zend_ast *ast, zend_ast \
*return_type_ast, zend_bool is_ if (type != 0) {
arg_infos->type_hint = type;
} else {
- if (zend_is_const_default_class_ref(return_type_ast)) {
+ uint32_t fetch_type = zend_get_class_fetch_type_ast(return_type_ast);
+ if (fetch_type == ZEND_FETCH_CLASS_DEFAULT) {
class_name = zend_resolve_class_name_ast(return_type_ast);
zend_assert_valid_class_name(class_name);
} else {
+ zend_ensure_valid_class_fetch_type(fetch_type);
zend_string_addref(class_name);
- if (!is_method) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare a return type of %s \
outside of a class scope", class_name->val);
- return;
- }
}
arg_infos->type_hint = IS_OBJECT;
@@ -4302,10 +4315,12 @@ void zend_compile_params(zend_ast *ast, zend_ast \
*return_type_ast, zend_bool is_ if (type != 0) {
arg_info->type_hint = type;
} else {
- if (zend_is_const_default_class_ref(type_ast)) {
+ uint32_t fetch_type = zend_get_class_fetch_type_ast(type_ast);
+ if (fetch_type == ZEND_FETCH_CLASS_DEFAULT) {
class_name = zend_resolve_class_name_ast(type_ast);
zend_assert_valid_class_name(class_name);
} else {
+ zend_ensure_valid_class_fetch_type(fetch_type);
zend_string_addref(class_name);
}
@@ -4626,7 +4641,7 @@ void zend_compile_func_decl(znode *result, zend_ast *ast) /* \
{{{ */ zend_stack_push(&CG(loop_var_stack), (void *) &dummy_var);
}
- zend_compile_params(params_ast, return_type_ast, is_method);
+ zend_compile_params(params_ast, return_type_ast);
if (uses_ast) {
zend_compile_closure_uses(uses_ast);
}
@@ -6329,13 +6344,10 @@ void zend_compile_resolve_class_name(znode *result, zend_ast \
*ast) /* {{{ */ {
zend_ast *name_ast = ast->child[0];
uint32_t fetch_type = zend_get_class_fetch_type(zend_ast_get_str(name_ast));
+ zend_ensure_valid_class_fetch_type(fetch_type);
switch (fetch_type) {
case ZEND_FETCH_CLASS_SELF:
- if (!CG(active_class_entry)) {
- zend_error_noreturn(E_COMPILE_ERROR,
- "Cannot access self::class when no class scope is active");
- }
if (CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) {
zval class_str_zv;
zend_ast *class_str_ast, *class_const_ast;
@@ -6354,11 +6366,7 @@ void zend_compile_resolve_class_name(znode *result, zend_ast \
*ast) /* {{{ */ break;
case ZEND_FETCH_CLASS_STATIC:
case ZEND_FETCH_CLASS_PARENT:
- if (!CG(active_class_entry)) {
- zend_error_noreturn(E_COMPILE_ERROR,
- "Cannot access %s::class when no class scope is active",
- fetch_type == ZEND_FETCH_CLASS_STATIC ? "static" : "parent");
- } else {
+ {
zval class_str_zv;
zend_ast *class_str_ast, *class_const_ast;
@@ -6611,15 +6619,12 @@ void zend_compile_const_expr_resolve_class_name(zend_ast \
**ast_ptr) /* {{{ */ {
zend_ast *ast = *ast_ptr;
zend_ast *name_ast = ast->child[0];
- uint32_t fetch_type = zend_get_class_fetch_type(zend_ast_get_str(name_ast));
zval result;
+ uint32_t fetch_type = zend_get_class_fetch_type(zend_ast_get_str(name_ast));
+ zend_ensure_valid_class_fetch_type(fetch_type);
switch (fetch_type) {
case ZEND_FETCH_CLASS_SELF:
- if (!CG(active_class_entry)) {
- zend_error_noreturn(E_COMPILE_ERROR,
- "Cannot access self::class when no class scope is active");
- }
ZVAL_STR_COPY(&result, CG(active_class_entry)->name);
break;
case ZEND_FETCH_CLASS_STATIC:
--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic