summaryrefslogtreecommitdiff
path: root/Zend/zend_compile.c
diff options
context:
space:
mode:
authorXinchen Hui <laruence@gmail.com>2015-05-26 14:17:21 +0800
committerXinchen Hui <laruence@gmail.com>2015-05-26 14:17:21 +0800
commit49b10ee264c88edc4fc52d4ab9ae1ca843be7c1f (patch)
tree37914a2c0af1c7a5a1691d7d2973f9cf0b1263da /Zend/zend_compile.c
parent9f1788f00db71cf06f62b02a24973ce2718efeb6 (diff)
parent770a4629432a8722bd1ad46eee9bccdd00c61e30 (diff)
downloadphp-git-49b10ee264c88edc4fc52d4ab9ae1ca843be7c1f.tar.gz
Merge branch 'master' into merge-fastcgi
Diffstat (limited to 'Zend/zend_compile.c')
-rw-r--r--Zend/zend_compile.c217
1 files changed, 132 insertions, 85 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 4721ecd939..39c7aa302c 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -557,7 +557,10 @@ static int zend_add_const_name_literal(zend_op_array *op_array, zend_string *nam
op.constant = zend_add_literal(CG(active_op_array), &_c); \
} while (0)
-void zend_stop_lexing(void) {
+void zend_stop_lexing(void)
+{
+ if(LANG_SCNG(on_event)) LANG_SCNG(on_event)(ON_STOP, END, 0);
+
LANG_SCNG(yy_cursor) = LANG_SCNG(yy_limit);
}
@@ -1345,6 +1348,88 @@ static inline zend_bool class_name_refers_to_active_ce(zend_string *class_name,
}
/* }}} */
+uint32_t zend_get_class_fetch_type(zend_string *name) /* {{{ */
+{
+ if (zend_string_equals_literal_ci(name, "self")) {
+ return ZEND_FETCH_CLASS_SELF;
+ } else if (zend_string_equals_literal_ci(name, "parent")) {
+ return ZEND_FETCH_CLASS_PARENT;
+ } else if (zend_string_equals_literal_ci(name, "static")) {
+ return ZEND_FETCH_CLASS_STATIC;
+ } else {
+ return ZEND_FETCH_CLASS_DEFAULT;
+ }
+}
+/* }}} */
+
+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));
+}
+/* }}} */
+
+static void zend_ensure_valid_class_fetch_type(uint32_t fetch_type) /* {{{ */
+{
+ if (fetch_type != ZEND_FETCH_CLASS_DEFAULT && !CG(active_class_entry) && zend_is_scope_known()) {
+ 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");
+ }
+}
+/* }}} */
+
+static zend_bool zend_try_compile_const_expr_resolve_class_name(zval *zv, zend_ast *class_ast, zend_ast *name_ast, zend_bool constant) /* {{{ */
+{
+ uint32_t fetch_type;
+
+ if (name_ast->kind != ZEND_AST_ZVAL) {
+ return 0;
+ }
+
+ if (!zend_string_equals_literal_ci(zend_ast_get_str(name_ast), "class")) {
+ return 0;
+ }
+
+ if (class_ast->kind != ZEND_AST_ZVAL) {
+ zend_error_noreturn(E_COMPILE_ERROR,
+ "Dynamic class names are not allowed in compile-time ::class fetch");
+ }
+
+ fetch_type = zend_get_class_fetch_type(zend_ast_get_str(class_ast));
+ zend_ensure_valid_class_fetch_type(fetch_type);
+
+ switch (fetch_type) {
+ case ZEND_FETCH_CLASS_SELF:
+ if (constant || (CG(active_class_entry) && zend_is_scope_known())) {
+ ZVAL_STR_COPY(zv, CG(active_class_entry)->name);
+ } else {
+ ZVAL_NULL(zv);
+ }
+ return 1;
+ case ZEND_FETCH_CLASS_STATIC:
+ case ZEND_FETCH_CLASS_PARENT:
+ if (constant) {
+ zend_error_noreturn(E_COMPILE_ERROR,
+ "%s::class cannot be used for compile-time class name resolution",
+ fetch_type == ZEND_FETCH_CLASS_STATIC ? "static" : "parent"
+ );
+ } else {
+ ZVAL_NULL(zv);
+ }
+ return 1;
+ case ZEND_FETCH_CLASS_DEFAULT:
+ ZVAL_STR(zv, zend_resolve_class_name_ast(class_ast));
+ return 1;
+ EMPTY_SWITCH_DEFAULT_CASE()
+ }
+}
+/* }}} */
+
static zend_bool zend_try_ct_eval_class_const(zval *zv, zend_string *class_name, zend_string *name) /* {{{ */
{
uint32_t fetch_type = zend_get_class_fetch_type(class_name);
@@ -1625,41 +1710,6 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify
}
/* }}} */
-uint32_t zend_get_class_fetch_type(zend_string *name) /* {{{ */
-{
- if (zend_string_equals_literal_ci(name, "self")) {
- return ZEND_FETCH_CLASS_SELF;
- } else if (zend_string_equals_literal_ci(name, "parent")) {
- return ZEND_FETCH_CLASS_PARENT;
- } else if (zend_string_equals_literal_ci(name, "static")) {
- return ZEND_FETCH_CLASS_STATIC;
- } else {
- return ZEND_FETCH_CLASS_DEFAULT;
- }
-}
-/* }}} */
-
-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));
-}
-/* }}} */
-
-static void zend_ensure_valid_class_fetch_type(uint32_t fetch_type) /* {{{ */
-{
- if (fetch_type != ZEND_FETCH_CLASS_DEFAULT && !CG(active_class_entry) && zend_is_scope_known()) {
- 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)];
@@ -2164,14 +2214,6 @@ static zend_op *zend_compile_simple_var_no_cv(znode *result, zend_ast *ast, uint
znode name_node;
zend_op *opline;
- /* there is a chance someone is accessing $this */
- if (ast->kind != ZEND_AST_ZVAL
- && CG(active_op_array)->scope && CG(active_op_array)->this_var == (uint32_t)-1
- ) {
- zend_string *key = zend_string_init("this", sizeof("this") - 1, 0);
- CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), key);
- }
-
zend_compile_expr(&name_node, name_ast);
if (name_node.op_type == IS_CONST) {
convert_to_string(&name_node.u.constant);
@@ -2183,10 +2225,18 @@ static zend_op *zend_compile_simple_var_no_cv(znode *result, zend_ast *ast, uint
opline = zend_emit_op(result, ZEND_FETCH_R, &name_node, NULL);
}
- opline->extended_value = ZEND_FETCH_LOCAL;
- if (name_node.op_type == IS_CONST) {
- if (zend_is_auto_global(Z_STR(name_node.u.constant))) {
- opline->extended_value = ZEND_FETCH_GLOBAL;
+ if (name_node.op_type == IS_CONST &&
+ zend_is_auto_global(Z_STR(name_node.u.constant))) {
+
+ opline->extended_value = ZEND_FETCH_GLOBAL;
+ } else {
+ opline->extended_value = ZEND_FETCH_LOCAL;
+ /* there is a chance someone is accessing $this */
+ if (ast->kind != ZEND_AST_ZVAL
+ && CG(active_op_array)->scope && CG(active_op_array)->this_var == (uint32_t)-1
+ ) {
+ zend_string *key = zend_string_init("this", sizeof("this") - 1, 0);
+ CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), key);
}
}
@@ -4747,6 +4797,11 @@ void zend_compile_class_const_decl(zend_ast *ast) /* {{{ */
zend_string *name = zend_ast_get_str(name_ast);
zval value_zv;
+ if (zend_string_equals_literal_ci(name, "class")) {
+ zend_error(E_COMPILE_ERROR,
+ "A class constant must not be called 'class'; it is reserved for class name fetching");
+ }
+
zend_const_expr_to_zval(&value_zv, value_ast);
name = zend_new_interned_string_safe(name);
@@ -6313,6 +6368,16 @@ void zend_compile_class_const(znode *result, zend_ast *ast) /* {{{ */
zend_op *opline;
zend_string *resolved_name;
+ if (zend_try_compile_const_expr_resolve_class_name(&result->u.constant, class_ast, const_ast, 0)) {
+ if (Z_TYPE(result->u.constant) == IS_NULL) {
+ zend_op *opline = zend_emit_op_tmp(result, ZEND_FETCH_CLASS_NAME, NULL, NULL);
+ opline->extended_value = zend_get_class_fetch_type(zend_ast_get_str(class_ast));
+ } else {
+ result->op_type = IS_CONST;
+ }
+ return;
+ }
+
zend_eval_const_expr(&class_ast);
zend_eval_const_expr(&const_ast);
@@ -6324,6 +6389,10 @@ void zend_compile_class_const(znode *result, zend_ast *ast) /* {{{ */
return;
}
}
+ if (const_ast->kind == ZEND_AST_ZVAL && zend_string_equals_literal_ci(zend_ast_get_str(const_ast), "class")) {
+ zend_error_noreturn(E_COMPILE_ERROR,
+ "Dynamic class names are not allowed in compile-time ::class fetch");
+ }
if (zend_is_const_default_class_ref(class_ast)) {
class_node.op_type = IS_CONST;
@@ -6536,7 +6605,7 @@ zend_bool zend_is_allowed_in_const_expr(zend_ast_kind kind) /* {{{ */
|| kind == ZEND_AST_CONDITIONAL || kind == ZEND_AST_DIM
|| kind == ZEND_AST_ARRAY || kind == ZEND_AST_ARRAY_ELEM
|| kind == ZEND_AST_CONST || kind == ZEND_AST_CLASS_CONST
- || kind == ZEND_AST_RESOLVE_CLASS_NAME || kind == ZEND_AST_MAGIC_CONST;
+ || kind == ZEND_AST_MAGIC_CONST;
}
/* }}} */
@@ -6555,6 +6624,11 @@ void zend_compile_const_expr_class_const(zend_ast **ast_ptr) /* {{{ */
"Dynamic class names are not allowed in compile-time class constant references");
}
+ if (zend_try_compile_const_expr_resolve_class_name(&result, class_ast, const_ast, 1)) {
+ *ast_ptr = zend_ast_create_zval(&result);
+ return;
+ }
+
class_name = zend_ast_get_str(class_ast);
fetch_type = zend_get_class_fetch_type(class_name);
@@ -6610,36 +6684,6 @@ void zend_compile_const_expr_const(zend_ast **ast_ptr) /* {{{ */
}
/* }}} */
-void zend_compile_const_expr_resolve_class_name(zend_ast **ast_ptr) /* {{{ */
-{
- zend_ast *ast = *ast_ptr;
- zend_ast *name_ast = ast->child[0];
- 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:
- ZVAL_STR_COPY(&result, CG(active_class_entry)->name);
- break;
- case ZEND_FETCH_CLASS_STATIC:
- case ZEND_FETCH_CLASS_PARENT:
- zend_error_noreturn(E_COMPILE_ERROR,
- "%s::class cannot be used for compile-time class name resolution",
- fetch_type == ZEND_FETCH_CLASS_STATIC ? "static" : "parent"
- );
- break;
- case ZEND_FETCH_CLASS_DEFAULT:
- ZVAL_STR(&result, zend_resolve_class_name_ast(name_ast));
- break;
- EMPTY_SWITCH_DEFAULT_CASE()
- }
-
- zend_ast_destroy(ast);
- *ast_ptr = zend_ast_create_zval(&result);
-}
-/* }}} */
-
void zend_compile_const_expr_magic_const(zend_ast **ast_ptr) /* {{{ */
{
zend_ast *ast = *ast_ptr;
@@ -6678,9 +6722,6 @@ void zend_compile_const_expr(zend_ast **ast_ptr) /* {{{ */
case ZEND_AST_CONST:
zend_compile_const_expr_const(ast_ptr);
break;
- case ZEND_AST_RESOLVE_CLASS_NAME:
- zend_compile_const_expr_resolve_class_name(ast_ptr);
- break;
case ZEND_AST_MAGIC_CONST:
zend_compile_const_expr_magic_const(ast_ptr);
break;
@@ -6955,9 +6996,6 @@ void zend_compile_expr(znode *result, zend_ast *ast) /* {{{ */
case ZEND_AST_CLASS_CONST:
zend_compile_class_const(result, ast);
return;
- case ZEND_AST_RESOLVE_CLASS_NAME:
- zend_compile_resolve_class_name(result, ast);
- return;
case ZEND_AST_ENCAPS_LIST:
zend_compile_encaps_list(result, ast);
return;
@@ -7127,9 +7165,18 @@ void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */
zend_ast *name_ast = ast->child[1];
zend_string *resolved_name;
+ if (zend_try_compile_const_expr_resolve_class_name(&result, class_ast, name_ast, 1)) {
+ break;
+ }
+
zend_eval_const_expr(&class_ast);
zend_eval_const_expr(&name_ast);
+ if (name_ast->kind == ZEND_AST_ZVAL && zend_string_equals_literal_ci(zend_ast_get_str(name_ast), "class")) {
+ zend_error_noreturn(E_COMPILE_ERROR,
+ "Dynamic class names are not allowed in compile-time ::class fetch");
+ }
+
if (class_ast->kind != ZEND_AST_ZVAL || name_ast->kind != ZEND_AST_ZVAL) {
return;
}