diff options
Diffstat (limited to 'Zend')
-rw-r--r-- | Zend/Makefile.am | 3 | ||||
-rw-r--r-- | Zend/Zend.dsp | 4 | ||||
-rw-r--r-- | Zend/ZendTS.dsp | 4 | ||||
-rw-r--r-- | Zend/zend.h | 23 | ||||
-rw-r--r-- | Zend/zend_API.c | 57 | ||||
-rw-r--r-- | Zend/zend_ast.c | 128 | ||||
-rw-r--r-- | Zend/zend_ast.h | 60 | ||||
-rw-r--r-- | Zend/zend_builtin_functions.c | 7 | ||||
-rw-r--r-- | Zend/zend_compile.c | 25 | ||||
-rw-r--r-- | Zend/zend_compile.h | 1 | ||||
-rw-r--r-- | Zend/zend_execute_API.c | 334 | ||||
-rw-r--r-- | Zend/zend_language_parser.y | 34 | ||||
-rw-r--r-- | Zend/zend_operators.h | 3 | ||||
-rw-r--r-- | Zend/zend_variables.c | 10 | ||||
-rw-r--r-- | Zend/zend_vm_def.h | 64 | ||||
-rw-r--r-- | Zend/zend_vm_execute.h | 92 |
16 files changed, 580 insertions, 269 deletions
diff --git a/Zend/Makefile.am b/Zend/Makefile.am index 6417f3eb14..d0316083b0 100644 --- a/Zend/Makefile.am +++ b/Zend/Makefile.am @@ -18,7 +18,8 @@ libZend_la_SOURCES=\ zend_default_classes.c \ zend_iterators.c zend_interfaces.c zend_exceptions.c \ zend_strtod.c zend_closures.c zend_float.c zend_string.c zend_signal.c \ - zend_generators.c + zend_generators.c \ + zend_ast.c libZend_la_LDFLAGS = libZend_la_LIBADD = @ZEND_EXTRA_LIBS@ diff --git a/Zend/Zend.dsp b/Zend/Zend.dsp index 23ebd4532b..9baf628b84 100644 --- a/Zend/Zend.dsp +++ b/Zend/Zend.dsp @@ -119,6 +119,10 @@ SOURCE=.\zend_API.c # End Source File
# Begin Source File
+SOURCE=.\zend_ast.c
+# End Source File
+# Begin Source File
+
SOURCE=.\zend_builtin_functions.c
# End Source File
# Begin Source File
diff --git a/Zend/ZendTS.dsp b/Zend/ZendTS.dsp index 3be2c58bed..5dfa24d5b9 100644 --- a/Zend/ZendTS.dsp +++ b/Zend/ZendTS.dsp @@ -140,6 +140,10 @@ SOURCE=.\zend_alloc.c # End Source File
# Begin Source File
+SOURCE=.\zend_ast.c
+# End Source File
+# Begin Source File
+
SOURCE=.\zend_API.c
# End Source File
# Begin Source File
diff --git a/Zend/zend.h b/Zend/zend.h index acbb6acaf7..7ccd0814e0 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -317,6 +317,7 @@ typedef struct _zend_object { } zend_object; #include "zend_object_handlers.h" +#include "zend_ast.h" typedef union _zvalue_value { long lval; /* long value */ @@ -327,6 +328,7 @@ typedef union _zvalue_value { } str; HashTable *ht; /* hash table value */ zend_object_value obj; + zend_ast *ast; } zvalue_value; struct _zval_struct { @@ -577,17 +579,18 @@ typedef int (*zend_write_func_t)(const char *str, uint str_length); /* data types */ /* All data types <= IS_BOOL have their constructor/destructors skipped */ -#define IS_NULL 0 -#define IS_LONG 1 -#define IS_DOUBLE 2 -#define IS_BOOL 3 -#define IS_ARRAY 4 -#define IS_OBJECT 5 -#define IS_STRING 6 -#define IS_RESOURCE 7 -#define IS_CONSTANT 8 +#define IS_NULL 0 +#define IS_LONG 1 +#define IS_DOUBLE 2 +#define IS_BOOL 3 +#define IS_ARRAY 4 +#define IS_OBJECT 5 +#define IS_STRING 6 +#define IS_RESOURCE 7 +#define IS_CONSTANT 8 #define IS_CONSTANT_ARRAY 9 -#define IS_CALLABLE 10 +#define IS_CONSTANT_AST 10 +#define IS_CALLABLE 11 /* Ugly hack to support constants as static array indices */ #define IS_CONSTANT_TYPE_MASK 0x00f diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 5fa7fb908e..3051d19729 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -1053,34 +1053,37 @@ ZEND_API void zend_merge_properties(zval *obj, HashTable *properties, int destro static int zval_update_class_constant(zval **pp, int is_static, int offset TSRMLS_DC) /* {{{ */ { - if ((Z_TYPE_PP(pp) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT || - (Z_TYPE_PP(pp) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT_ARRAY) { - zend_class_entry **scope = EG(in_execution)?&EG(scope):&CG(active_class_entry); - - if ((*scope)->parent) { - zend_class_entry *ce = *scope; - HashPosition pos; - zend_property_info *prop_info; - - do { - for (zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos); - zend_hash_get_current_data_ex(&ce->properties_info, (void **) &prop_info, &pos) == SUCCESS; - zend_hash_move_forward_ex(&ce->properties_info, &pos)) { - if (is_static == ((prop_info->flags & ZEND_ACC_STATIC) != 0) && - offset == prop_info->offset) { - int ret; - zend_class_entry *old_scope = *scope; - *scope = prop_info->ce; - ret = zval_update_constant(pp, (void*)1 TSRMLS_CC); - *scope = old_scope; - return ret; - } - } - ce = ce->parent; - } while (ce); - + switch (Z_TYPE_PP(pp) & IS_CONSTANT_TYPE_MASK) { + case IS_CONSTANT: + case IS_CONSTANT_ARRAY: + case IS_CONSTANT_AST: { + zend_class_entry **scope = EG(in_execution)?&EG(scope):&CG(active_class_entry); + + if ((*scope)->parent) { + zend_class_entry *ce = *scope; + HashPosition pos; + zend_property_info *prop_info; + + do { + for (zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos); + zend_hash_get_current_data_ex(&ce->properties_info, (void **) &prop_info, &pos) == SUCCESS; + zend_hash_move_forward_ex(&ce->properties_info, &pos)) { + if (is_static == ((prop_info->flags & ZEND_ACC_STATIC) != 0) && + offset == prop_info->offset) { + int ret; + zend_class_entry *old_scope = *scope; + *scope = prop_info->ce; + ret = zval_update_constant(pp, (void*)1 TSRMLS_CC); + *scope = old_scope; + return ret; + } + } + ce = ce->parent; + } while (ce); + + } + return zval_update_constant(pp, (void*)1 TSRMLS_CC); } - return zval_update_constant(pp, (void*)1 TSRMLS_CC); } return 0; } diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c new file mode 100644 index 0000000000..705c4df465 --- /dev/null +++ b/Zend/zend_ast.c @@ -0,0 +1,128 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998-2013 Zend Technologies Ltd. (http://www.zend.com) | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.00 of the Zend license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.zend.com/license/2_00.txt. | + | If you did not receive a copy of the Zend license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@zend.com so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Bob Weinand <bwoebi@php.net> | + +----------------------------------------------------------------------+ +*/ + +/* $Id$ */ + +#include "zend_ast.h" +#include "zend_execute.h" + +#define OP_IS_CONST_THEN(op, do_code) \ + switch (Z_TYPE_P(op) & IS_CONSTANT_TYPE_MASK) { \ + case IS_CONSTANT: \ + case IS_CONSTANT_ARRAY: \ + case IS_CONSTANT_AST: { \ + do_code \ + } \ + } + +#define OP_IS_NOT_CONST_THEN(op, do_code) \ + switch (Z_TYPE_P(op) & IS_CONSTANT_TYPE_MASK) { \ + case IS_CONSTANT: \ + case IS_CONSTANT_ARRAY: \ + case IS_CONSTANT_AST: \ + break; \ +\ + default: { \ + do_code \ + } \ + } + +#define COPY_ZVAL_TO_OP(nr) \ + Z_AST_P(result)->ops[nr] = emalloc(sizeof(zval)); \ + *Z_AST_P(result)->ops[nr] = *op##nr; + +void zend_ast_add(zval *result, intermediary_ast_function_type func, char op_count) { + zend_ast *ast = emalloc(sizeof(zend_ast)); + ast->op_count = op_count; + ast->ops = emalloc(op_count * sizeof(zval *)); + ast->refcount = 1; + ast->func = func; + Z_AST_P(result) = ast; + Z_TYPE_P(result) = IS_CONSTANT_AST; +} + +/* Do operations on constant operators at compile time (AST building time) */ + +void zend_ast_add_unary(zval *result, unary_ast_func func, zval *op0) { + OP_IS_NOT_CONST_THEN(op0, + func(result, op0); + return; + ) + + zend_ast_add(result, (intermediary_ast_function_type)func, 1); + COPY_ZVAL_TO_OP(0) +} + +void zend_ast_add_binary(zval *result, binary_ast_func func, zval *op0, zval *op1) { + OP_IS_NOT_CONST_THEN(op0, OP_IS_NOT_CONST_THEN(op1, + func(result, op0, op1); + return; + )) + + zend_ast_add(result, (intermediary_ast_function_type)func, 2); + COPY_ZVAL_TO_OP(0) + COPY_ZVAL_TO_OP(1) +} + +void zend_ast_add_ternary(zval *result, ternary_ast_func func, zval *op0, zval *op1, zval *op2) { + OP_IS_NOT_CONST_THEN(op0, OP_IS_NOT_CONST_THEN(op1, OP_IS_NOT_CONST_THEN(op2, + func(result, op0, op1, op2); + return; + ))) + + zend_ast_add(result, (intermediary_ast_function_type)func, 3); + COPY_ZVAL_TO_OP(0) + COPY_ZVAL_TO_OP(1) + COPY_ZVAL_TO_OP(2) +} + +void zend_ast_evaluate(zval *result, zend_ast *ast TSRMLS_DC) { + int i; + + for (i = ast->op_count; i--;) { + OP_IS_CONST_THEN(ast->ops[i], + zval_update_constant_ex(&ast->ops[i], (void *)1, NULL TSRMLS_CC); + ) + } + + switch (ast->op_count) { + case 1: + ((unary_ast_func)ast->func)(result, ast->ops[0]); + break; + case 2: + ((binary_ast_func)ast->func)(result, ast->ops[0], ast->ops[1]); + break; + case 3: + ((ternary_ast_func)ast->func)(result, ast->ops[0], ast->ops[1], ast->ops[2]); + break; + } +} + +void zend_ast_destroy(zend_ast *ast TSRMLS_DC) { + int i; + + for (i = ast->op_count; i--;) { + if (!Z_DELREF_P(ast->ops[i])) { + zval_dtor(ast->ops[i]); + efree(ast->ops[i]); + } + } + + efree(ast->ops); + efree(ast); +} diff --git a/Zend/zend_ast.h b/Zend/zend_ast.h new file mode 100644 index 0000000000..9841c3463e --- /dev/null +++ b/Zend/zend_ast.h @@ -0,0 +1,60 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998-2013 Zend Technologies Ltd. (http://www.zend.com) | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.00 of the Zend license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.zend.com/license/2_00.txt. | + | If you did not receive a copy of the Zend license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@zend.com so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Bob Weinand <bwoebi@php.net> | + +----------------------------------------------------------------------+ +*/ + +/* $Id$ */ + +#ifndef ZEND_AST_H +#define ZEND_AST_H + +typedef struct _zend_ast zend_ast; + +#include "zend.h" + +typedef void(*intermediary_ast_function_type)(zval *, ...); +typedef int(*unary_ast_func)(zval *result, zval *op0); +typedef int(*binary_ast_func)(zval *result, zval *op0, zval *op1); +typedef int(*ternary_ast_func)(zval *result, zval *op0, zval *op1, zval *op2); + +struct _zend_ast { + char op_count; + zval **ops; + intermediary_ast_function_type func; + int refcount; +}; + +void zend_ast_add_unary(zval *result, unary_ast_func func, zval *op0); +void zend_ast_add_binary(zval *result, binary_ast_func func, zval *op0, zval *op1); +void zend_ast_add_ternary(zval *result, ternary_ast_func func, zval *op0, zval *op1, zval *op2); + +void zend_ast_evaluate(zval *result, zend_ast *ast TSRMLS_DC); + +void zend_ast_destroy(zend_ast *ast TSRMLS_DC); + +#define ZEND_AST_ADD_REF(ast) ++ast->refcount + +static inline int ZEND_AST_DEL_REF(zend_ast *ast) { + if (ast->refcount == 1) { + TSRMLS_FETCH(); + + zend_ast_destroy(ast TSRMLS_CC); + return 0; + } + return --ast->refcount; +} + +#endif diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index 55e5f34e83..b3b7529d9b 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -946,8 +946,11 @@ static void add_class_vars(zend_class_entry *ce, int statics, zval *return_value /* this is necessary to make it able to work with default array * properties, returned to user */ - if (Z_TYPE_P(prop_copy) == IS_CONSTANT_ARRAY || (Z_TYPE_P(prop_copy) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) { - zval_update_constant(&prop_copy, 0 TSRMLS_CC); + switch (Z_TYPE_P(prop_copy) & IS_CONSTANT_TYPE_MASK) { + case IS_CONSTANT: + case IS_CONSTANT_ARRAY: + case IS_CONSTANT_AST: + zval_update_constant(&prop_copy, 0 TSRMLS_CC); } add_assoc_zval(return_value, key, prop_copy); diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 7ee8dd1e74..f3bf5be380 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1891,7 +1891,7 @@ void zend_do_receive_param(zend_uchar op, znode *varname, const znode *initializ if (class_type->u.constant.type == IS_ARRAY) { cur_arg_info->type_hint = IS_ARRAY; if (op == ZEND_RECV_INIT) { - if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL"))) { + if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL")) || Z_TYPE(initialization->u.constant) == IS_CONSTANT_AST) { cur_arg_info->allow_null = 1; } else if (Z_TYPE(initialization->u.constant) != IS_ARRAY && Z_TYPE(initialization->u.constant) != IS_CONSTANT_ARRAY) { zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters with array type hint can only be an array or NULL"); @@ -1900,7 +1900,7 @@ void zend_do_receive_param(zend_uchar op, znode *varname, const znode *initializ } else if (class_type->u.constant.type == IS_CALLABLE) { cur_arg_info->type_hint = IS_CALLABLE; if (op == ZEND_RECV_INIT) { - if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL"))) { + if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL")) || Z_TYPE(initialization->u.constant) == IS_CONSTANT_AST) { cur_arg_info->allow_null = 1; } else { zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters with callable type hint can only be NULL"); @@ -1915,7 +1915,7 @@ void zend_do_receive_param(zend_uchar op, znode *varname, const znode *initializ cur_arg_info->class_name = Z_STRVAL(class_type->u.constant); cur_arg_info->class_name_len = Z_STRLEN(class_type->u.constant); if (op == ZEND_RECV_INIT) { - if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL"))) { + if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL")) || Z_TYPE(initialization->u.constant) == IS_CONSTANT_AST) { cur_arg_info->allow_null = 1; } else { zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters with a class type hint can only be NULL"); @@ -5530,7 +5530,8 @@ static zend_constant* zend_get_ct_const(const zval *const_name, int all_internal (c->flags & CONST_PERSISTENT) && !(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION) && Z_TYPE(c->value) != IS_CONSTANT && - Z_TYPE(c->value) != IS_CONSTANT_ARRAY) { + Z_TYPE(c->value) != IS_CONSTANT_ARRAY && + Z_TYPE(c->value) != IS_CONSTANT_AST) { return c; } return NULL; @@ -5772,7 +5773,7 @@ void zend_do_add_static_array_element(znode *result, znode *offset, const znode ALLOC_ZVAL(element); *element = expr->u.constant; if (offset) { - switch (offset->u.constant.type & IS_CONSTANT_TYPE_MASK) { + switch (Z_TYPE(offset->u.constant) & IS_CONSTANT_TYPE_MASK) { case IS_CONSTANT: /* Ugly hack to denote that this value has a constant index */ Z_TYPE_P(element) |= IS_CONSTANT_INDEX; @@ -5782,6 +5783,20 @@ void zend_do_add_static_array_element(znode *result, znode *offset, const znode zend_symtable_update(Z_ARRVAL(result->u.constant), Z_STRVAL(offset->u.constant), Z_STRLEN(offset->u.constant)+3, &element, sizeof(zval *), NULL); zval_dtor(&offset->u.constant); break; + case IS_CONSTANT_AST: { + /* Another ugly hack to store the data about the AST in the array */ + char* key; + int len = sizeof(zend_ast *); + Z_TYPE_P(element) |= IS_CONSTANT_INDEX; + + key = emalloc(len + 2); + *(zend_ast **)key = Z_AST(offset->u.constant); + key[len] = Z_TYPE(offset->u.constant); + key[len + 1] = 0; + zend_symtable_update(Z_ARRVAL(result->u.constant), key, len + 2, &element, sizeof(zval *), NULL); + efree(key); + } + break; case IS_STRING: zend_symtable_update(Z_ARRVAL(result->u.constant), Z_STRVAL(offset->u.constant), Z_STRLEN(offset->u.constant)+1, &element, sizeof(zval *), NULL); zval_dtor(&offset->u.constant); diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index f9520c98ea..bbc6e47383 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -23,6 +23,7 @@ #define ZEND_COMPILE_H #include "zend.h" +#include "zend_ast.h" #ifdef HAVE_STDARG_H # include <stdarg.h> diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 779e6d886f..eabebacce4 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -478,188 +478,208 @@ ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *sco if (IS_CONSTANT_VISITED(p)) { zend_error(E_ERROR, "Cannot declare self-referencing constant '%s'", Z_STRVAL_P(p)); - } else if ((Z_TYPE_P(p) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) { - int refcount; - zend_uchar is_ref; + return FAILURE; + } + switch (Z_TYPE_P(p) & IS_CONSTANT_TYPE_MASK) { + case IS_CONSTANT: { + int refcount; + zend_uchar is_ref; - SEPARATE_ZVAL_IF_NOT_REF(pp); - p = *pp; + SEPARATE_ZVAL_IF_NOT_REF(pp); + p = *pp; - MARK_CONSTANT_VISITED(p); + MARK_CONSTANT_VISITED(p); - refcount = Z_REFCOUNT_P(p); - is_ref = Z_ISREF_P(p); + refcount = Z_REFCOUNT_P(p); + is_ref = Z_ISREF_P(p); - if (!zend_get_constant_ex(p->value.str.val, p->value.str.len, &const_value, scope, Z_REAL_TYPE_P(p) TSRMLS_CC)) { - char *actual = Z_STRVAL_P(p); + if (!zend_get_constant_ex(p->value.str.val, p->value.str.len, &const_value, scope, Z_REAL_TYPE_P(p) TSRMLS_CC)) { + char *actual = Z_STRVAL_P(p); - if ((colon = (char*)zend_memrchr(Z_STRVAL_P(p), ':', Z_STRLEN_P(p)))) { - zend_error(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(p)); - Z_STRLEN_P(p) -= ((colon - Z_STRVAL_P(p)) + 1); - if (inline_change) { - colon = estrndup(colon, Z_STRLEN_P(p)); - str_efree(Z_STRVAL_P(p)); - Z_STRVAL_P(p) = colon; - } else { - Z_STRVAL_P(p) = colon + 1; - } - } else { - char *save = actual, *slash; - int actual_len = Z_STRLEN_P(p); - if ((Z_TYPE_P(p) & IS_CONSTANT_UNQUALIFIED) && (slash = (char *)zend_memrchr(actual, '\\', actual_len))) { - actual = slash + 1; - actual_len -= (actual - Z_STRVAL_P(p)); + if ((colon = (char*)zend_memrchr(Z_STRVAL_P(p), ':', Z_STRLEN_P(p)))) { + zend_error(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(p)); + Z_STRLEN_P(p) -= ((colon - Z_STRVAL_P(p)) + 1); if (inline_change) { - actual = estrndup(actual, actual_len); - Z_STRVAL_P(p) = actual; - Z_STRLEN_P(p) = actual_len; - } - } - if (actual[0] == '\\') { - if (inline_change) { - memmove(Z_STRVAL_P(p), Z_STRVAL_P(p)+1, Z_STRLEN_P(p)); - --Z_STRLEN_P(p); + colon = estrndup(colon, Z_STRLEN_P(p)); + str_efree(Z_STRVAL_P(p)); + Z_STRVAL_P(p) = colon; } else { - ++actual; + Z_STRVAL_P(p) = colon + 1; } - --actual_len; - } - if ((Z_TYPE_P(p) & IS_CONSTANT_UNQUALIFIED) == 0) { - int fix_save = 0; - if (save[0] == '\\') { - save++; - fix_save = 1; + } else { + char *save = actual, *slash; + int actual_len = Z_STRLEN_P(p); + if ((Z_TYPE_P(p) & IS_CONSTANT_UNQUALIFIED) && (slash = (char *)zend_memrchr(actual, '\\', actual_len))) { + actual = slash + 1; + actual_len -= (actual - Z_STRVAL_P(p)); + if (inline_change) { + actual = estrndup(actual, actual_len); + Z_STRVAL_P(p) = actual; + Z_STRLEN_P(p) = actual_len; + } } - zend_error(E_ERROR, "Undefined constant '%s'", save); - if (fix_save) { - save--; + if (actual[0] == '\\') { + if (inline_change) { + memmove(Z_STRVAL_P(p), Z_STRVAL_P(p)+1, Z_STRLEN_P(p)); + --Z_STRLEN_P(p); + } else { + ++actual; + } + --actual_len; } - if (inline_change) { + if ((Z_TYPE_P(p) & IS_CONSTANT_UNQUALIFIED) == 0) { + int fix_save = 0; + if (save[0] == '\\') { + save++; + fix_save = 1; + } + zend_error(E_ERROR, "Undefined constant '%s'", save); + if (fix_save) { + save--; + } + if (inline_change) { + str_efree(save); + } + save = NULL; + } + if (inline_change && save && save != actual) { str_efree(save); } - save = NULL; - } - if (inline_change && save && save != actual) { - str_efree(save); + zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", actual, actual); + p->type = IS_STRING; + if (!inline_change) { + Z_STRVAL_P(p) = actual; + Z_STRLEN_P(p) = actual_len; + zval_copy_ctor(p); + } } - zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", actual, actual); - p->type = IS_STRING; - if (!inline_change) { - Z_STRVAL_P(p) = actual; - Z_STRLEN_P(p) = actual_len; - zval_copy_ctor(p); + } else { + if (inline_change) { + str_efree(Z_STRVAL_P(p)); } + *p = const_value; } - } else { - if (inline_change) { - str_efree(Z_STRVAL_P(p)); - } - *p = const_value; - } - Z_SET_REFCOUNT_P(p, refcount); - Z_SET_ISREF_TO_P(p, is_ref); - } else if (Z_TYPE_P(p) == IS_CONSTANT_ARRAY) { - zval **element, *new_val; - char *str_index; - uint str_index_len; - ulong num_index; - int ret; - - SEPARATE_ZVAL_IF_NOT_REF(pp); - p = *pp; - Z_TYPE_P(p) = IS_ARRAY; - - if (!inline_change) { - zval *tmp; - HashTable *tmp_ht = NULL; - - ALLOC_HASHTABLE(tmp_ht); - zend_hash_init(tmp_ht, zend_hash_num_elements(Z_ARRVAL_P(p)), NULL, ZVAL_PTR_DTOR, 0); - zend_hash_copy(tmp_ht, Z_ARRVAL_P(p), (copy_ctor_func_t) zval_deep_copy, (void *) &tmp, sizeof(zval *)); - Z_ARRVAL_P(p) = tmp_ht; + Z_SET_REFCOUNT_P(p, refcount); + Z_SET_ISREF_TO_P(p, is_ref); } - - /* First go over the array and see if there are any constant indices */ - zend_hash_internal_pointer_reset(Z_ARRVAL_P(p)); - while (zend_hash_get_current_data(Z_ARRVAL_P(p), (void **) &element) == SUCCESS) { - if (!(Z_TYPE_PP(element) & IS_CONSTANT_INDEX)) { - zend_hash_move_forward(Z_ARRVAL_P(p)); - continue; + break; + + case IS_CONSTANT_ARRAY: { + zval **element, *new_val; + char *str_index; + uint str_index_len; + ulong num_index; + int ret; + + SEPARATE_ZVAL_IF_NOT_REF(pp); + p = *pp; + Z_TYPE_P(p) = IS_ARRAY; + + if (!inline_change) { + zval *tmp; + HashTable *tmp_ht = NULL; + + ALLOC_HASHTABLE(tmp_ht); + zend_hash_init(tmp_ht, zend_hash_num_elements(Z_ARRVAL_P(p)), NULL, ZVAL_PTR_DTOR, 0); + zend_hash_copy(tmp_ht, Z_ARRVAL_P(p), (copy_ctor_func_t) zval_deep_copy, (void *) &tmp, sizeof(zval *)); + Z_ARRVAL_P(p) = tmp_ht; } - Z_TYPE_PP(element) &= ~IS_CONSTANT_INDEX; - if (zend_hash_get_current_key_ex(Z_ARRVAL_P(p), &str_index, &str_index_len, &num_index, 0, NULL) != HASH_KEY_IS_STRING) { - zend_hash_move_forward(Z_ARRVAL_P(p)); - continue; - } - if (!zend_get_constant_ex(str_index, str_index_len - 3, &const_value, scope, str_index[str_index_len - 2] TSRMLS_CC)) { - char *actual; - const char *save = str_index; - if ((colon = (char*)zend_memrchr(str_index, ':', str_index_len - 3))) { - zend_error(E_ERROR, "Undefined class constant '%s'", str_index); - str_index_len -= ((colon - str_index) + 1); - str_index = colon; - } else { - if (str_index[str_index_len - 2] & IS_CONSTANT_UNQUALIFIED) { - if ((actual = (char *)zend_memrchr(str_index, '\\', str_index_len - 3))) { - actual++; - str_index_len -= (actual - str_index); - str_index = actual; + + /* First go over the array and see if there are any constant indices */ + zend_hash_internal_pointer_reset(Z_ARRVAL_P(p)); + while (zend_hash_get_current_data(Z_ARRVAL_P(p), (void **) &element) == SUCCESS) { + if (!(Z_TYPE_PP(element) & IS_CONSTANT_INDEX)) { + zend_hash_move_forward(Z_ARRVAL_P(p)); + continue; + } + Z_TYPE_PP(element) &= ~IS_CONSTANT_INDEX; + if (zend_hash_get_current_key_ex(Z_ARRVAL_P(p), &str_index, &str_index_len, &num_index, 0, NULL) != HASH_KEY_IS_STRING) { + zend_hash_move_forward(Z_ARRVAL_P(p)); + continue; + } + if (str_index[str_index_len - 2] == IS_CONSTANT_AST) { + zend_ast_evaluate(&const_value, *(zend_ast **)str_index); + ZEND_AST_DEL_REF(*(zend_ast **)str_index); + } else if (!zend_get_constant_ex(str_index, str_index_len - 3, &const_value, scope, str_index[str_index_len - 2] TSRMLS_CC)) { + char *actual; + const char *save = str_index; + if ((colon = (char*)zend_memrchr(str_index, ':', str_index_len - 3))) { + zend_error(E_ERROR, "Undefined class constant '%s'", str_index); + str_index_len -= ((colon - str_index) + 1); + str_index = colon; + } else { + if (str_index[str_index_len - 2] & IS_CONSTANT_UNQUALIFIED) { + if ((actual = (char *)zend_memrchr(str_index, '\\', str_index_len - 3))) { + actual++; + str_index_len -= (actual - str_index); + str_index = actual; + } } + if (str_index[0] == '\\') { + ++str_index; + --str_index_len; + } + if (save[0] == '\\') { + ++save; + } + if ((str_index[str_index_len - 2] & IS_CONSTANT_UNQUALIFIED) == 0) { + zend_error(E_ERROR, "Undefined constant '%s'", save); + } + zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", str_index, str_index); } - if (str_index[0] == '\\') { - ++str_index; - --str_index_len; - } - if (save[0] == '\\') { - ++save; - } - if ((str_index[str_index_len - 2] & IS_CONSTANT_UNQUALIFIED) == 0) { - zend_error(E_ERROR, "Undefined constant '%s'", save); - } - zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", str_index, str_index); + ZVAL_STRINGL(&const_value, str_index, str_index_len-3, 1); } - ZVAL_STRINGL(&const_value, str_index, str_index_len-3, 1); - } - if (Z_REFCOUNT_PP(element) > 1) { - ALLOC_ZVAL(new_val); - *new_val = **element; - zval_copy_ctor(new_val); - Z_SET_REFCOUNT_P(new_val, 1); - Z_UNSET_ISREF_P(new_val); - - /* preserve this bit for inheritance */ - Z_TYPE_PP(element) |= IS_CONSTANT_INDEX; - zval_ptr_dtor(element); - *element = new_val; - } + if (Z_REFCOUNT_PP(element) > 1) { + ALLOC_ZVAL(new_val); + *new_val = **element; + zval_copy_ctor(new_val); + Z_SET_REFCOUNT_P(new_val, 1); + Z_UNSET_ISREF_P(new_val); + + /* preserve this bit for inheritance */ + Z_TYPE_PP(element) |= IS_CONSTANT_INDEX; + zval_ptr_dtor(element); + *element = new_val; + } - switch (Z_TYPE(const_value)) { - case IS_STRING: - ret = zend_symtable_update_current_key(Z_ARRVAL_P(p), Z_STRVAL(const_value), Z_STRLEN(const_value) + 1, HASH_UPDATE_KEY_IF_BEFORE); - break; - case IS_BOOL: - case IS_LONG: - ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL, 0, Z_LVAL(const_value), HASH_UPDATE_KEY_IF_BEFORE, NULL); - break; - case IS_DOUBLE: - ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL, 0, zend_dval_to_lval(Z_DVAL(const_value)), HASH_UPDATE_KEY_IF_BEFORE, NULL); - break; - case IS_NULL: - ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_STRING, "", 1, 0, HASH_UPDATE_KEY_IF_BEFORE, NULL); - break; - default: - ret = SUCCESS; - break; - } - if (ret == SUCCESS) { - zend_hash_move_forward(Z_ARRVAL_P(p)); + switch (Z_TYPE(const_value)) { + case IS_STRING: + ret = zend_symtable_update_current_key(Z_ARRVAL_P(p), Z_STRVAL(const_value), Z_STRLEN(const_value) + 1, HASH_UPDATE_KEY_IF_BEFORE); + break; + case IS_BOOL: + case IS_LONG: + ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL, 0, Z_LVAL(const_value), HASH_UPDATE_KEY_IF_BEFORE, NULL); + break; + case IS_DOUBLE: + ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL, 0, zend_dval_to_lval(Z_DVAL(const_value)), HASH_UPDATE_KEY_IF_BEFORE, NULL); + break; + case IS_NULL: + ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_STRING, "", 1, 0, HASH_UPDATE_KEY_IF_BEFORE, NULL); + break; + default: + ret = SUCCESS; + break; + } + if (ret == SUCCESS) { + zend_hash_move_forward(Z_ARRVAL_P(p)); + } + zval_dtor(&const_value); } - zval_dtor(&const_value); + zend_hash_apply_with_argument(Z_ARRVAL_P(p), (apply_func_arg_t) zval_update_constant_inline_change, (void *) scope TSRMLS_CC); + zend_hash_internal_pointer_reset(Z_ARRVAL_P(p)); + } + break; + + case IS_CONSTANT_AST: { + zend_ast *ast = Z_AST_P(p); + + MARK_CONSTANT_VISITED(p); + + zend_ast_evaluate(p, ast TSRMLS_CC); + ZEND_AST_DEL_REF(ast); } - zend_hash_apply_with_argument(Z_ARRVAL_P(p), (apply_func_arg_t) zval_update_constant_inline_change, (void *) scope TSRMLS_CC); - zend_hash_internal_pointer_reset(Z_ARRVAL_P(p)); } return 0; } diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index f76b77b555..517ae56e41 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -947,24 +947,46 @@ common_scalar: | T_START_HEREDOC T_END_HEREDOC { ZVAL_EMPTY_STRING(&$$.u.constant); INIT_PZVAL(&$$.u.constant); $$.op_type = IS_CONST; } ; +static_class_constant: + class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_CT, 0 TSRMLS_CC); } +; static_scalar: /* compile-time evaluated scalars */ - common_scalar { $$ = $1; } + static_scalar_value { $$ = $1; } +; + +static_scalar_value: + common_scalar { $$ = $1; } | static_class_name_scalar { $$ = $1; } | namespace_name { zend_do_fetch_constant(&$$, NULL, &$1, ZEND_CT, 1 TSRMLS_CC); } | T_NAMESPACE T_NS_SEPARATOR namespace_name { $$.op_type = IS_CONST; ZVAL_EMPTY_STRING(&$$.u.constant); zend_do_build_namespace_name(&$$, &$$, &$3 TSRMLS_CC); $3 = $$; zend_do_fetch_constant(&$$, NULL, &$3, ZEND_CT, 0 TSRMLS_CC); } | T_NS_SEPARATOR namespace_name { char *tmp = estrndup(Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); memcpy(&(tmp[1]), Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); tmp[0] = '\\'; efree(Z_STRVAL($2.u.constant)); Z_STRVAL($2.u.constant) = tmp; ++Z_STRLEN($2.u.constant); zend_do_fetch_constant(&$$, NULL, &$2, ZEND_CT, 0 TSRMLS_CC); } - | '+' static_scalar { ZVAL_LONG(&$1.u.constant, 0); add_function(&$2.u.constant, &$1.u.constant, &$2.u.constant TSRMLS_CC); $$ = $2; } - | '-' static_scalar { ZVAL_LONG(&$1.u.constant, 0); sub_function(&$2.u.constant, &$1.u.constant, &$2.u.constant TSRMLS_CC); $$ = $2; } | T_ARRAY '(' static_array_pair_list ')' { $$ = $3; Z_TYPE($$.u.constant) = IS_CONSTANT_ARRAY; } | '[' static_array_pair_list ']' { $$ = $2; Z_TYPE($$.u.constant) = IS_CONSTANT_ARRAY; } | static_class_constant { $$ = $1; } | T_CLASS_C { $$ = $1; } + | static_operation { $$ = $1; } +; + +static_operation: + static_scalar_value '+' static_scalar_value { zend_ast_add_binary(&$$.u.constant, add_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); } + | static_scalar_value '-' static_scalar_value { zend_ast_add_binary(&$$.u.constant, sub_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); } + | static_scalar_value '*' static_scalar_value { zend_ast_add_binary(&$$.u.constant, mul_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); } + | static_scalar_value '/' static_scalar_value { zend_ast_add_binary(&$$.u.constant, div_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); } + | static_scalar_value '%' static_scalar_value { zend_ast_add_binary(&$$.u.constant, mod_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); } + | '!' static_scalar_value { zend_ast_add_unary(&$$.u.constant, boolean_not_function, &$2.u.constant TSRMLS_CC); } + | '~' static_scalar_value { zend_ast_add_unary(&$$.u.constant, bitwise_not_function, &$2.u.constant TSRMLS_CC); } + | static_scalar_value '|' static_scalar_value { zend_ast_add_binary(&$$.u.constant, bitwise_or_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); } + | static_scalar_value '&' static_scalar_value { zend_ast_add_binary(&$$.u.constant, bitwise_and_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); } + | static_scalar_value '^' static_scalar_value { zend_ast_add_binary(&$$.u.constant, bitwise_xor_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); } + | static_scalar_value T_SL static_scalar_value { zend_ast_add_binary(&$$.u.constant, shift_left_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); } + | static_scalar_value T_SR static_scalar_value { zend_ast_add_binary(&$$.u.constant, shift_right_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); } + | static_scalar_value '.' static_scalar_value { zend_ast_add_binary(&$$.u.constant, concat_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); } + | '+' static_scalar_value { ZVAL_LONG(&$1.u.constant, 0); zend_ast_add_binary(&$$.u.constant, add_function, &$1.u.constant, &$2.u.constant TSRMLS_CC); } + | '-' static_scalar_value { ZVAL_LONG(&$1.u.constant, 0); zend_ast_add_binary(&$$.u.constant, sub_function, &$1.u.constant, &$2.u.constant TSRMLS_CC); } + | '(' static_scalar_value ')' { $$ = $2; } ; -static_class_constant: - class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_CT, 0 TSRMLS_CC); } -; scalar: T_STRING_VARNAME { $$ = $1; } diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h index 15ad79e4db..ce21af3d2e 100644 --- a/Zend/zend_operators.h +++ b/Zend/zend_operators.h @@ -443,6 +443,7 @@ END_EXTERN_C() #define Z_STRVAL(zval) (zval).value.str.val #define Z_STRLEN(zval) (zval).value.str.len #define Z_ARRVAL(zval) (zval).value.ht +#define Z_AST(zval) (zval).value.ast #define Z_OBJVAL(zval) (zval).value.obj #define Z_OBJ_HANDLE(zval) Z_OBJVAL(zval).handle #define Z_OBJ_HT(zval) Z_OBJVAL(zval).handlers @@ -458,6 +459,7 @@ END_EXTERN_C() #define Z_STRVAL_P(zval_p) Z_STRVAL(*zval_p) #define Z_STRLEN_P(zval_p) Z_STRLEN(*zval_p) #define Z_ARRVAL_P(zval_p) Z_ARRVAL(*zval_p) +#define Z_AST_P(zval_p) Z_AST(*zval_p) #define Z_OBJPROP_P(zval_p) Z_OBJPROP(*zval_p) #define Z_OBJCE_P(zval_p) Z_OBJCE(*zval_p) #define Z_RESVAL_P(zval_p) Z_RESVAL(*zval_p) @@ -473,6 +475,7 @@ END_EXTERN_C() #define Z_STRVAL_PP(zval_pp) Z_STRVAL(**zval_pp) #define Z_STRLEN_PP(zval_pp) Z_STRLEN(**zval_pp) #define Z_ARRVAL_PP(zval_pp) Z_ARRVAL(**zval_pp) +#define Z_AST_PP(zval_p) Z_AST(**zval_p) #define Z_OBJPROP_PP(zval_pp) Z_OBJPROP(**zval_pp) #define Z_OBJCE_PP(zval_pp) Z_OBJCE(**zval_pp) #define Z_RESVAL_PP(zval_pp) Z_RESVAL(**zval_pp) diff --git a/Zend/zend_variables.c b/Zend/zend_variables.c index d82e1642e7..095c16ca91 100644 --- a/Zend/zend_variables.c +++ b/Zend/zend_variables.c @@ -22,6 +22,7 @@ #include <stdio.h> #include "zend.h" #include "zend_API.h" +#include "zend_ast.h" #include "zend_globals.h" #include "zend_constants.h" #include "zend_list.h" @@ -47,6 +48,9 @@ ZEND_API void _zval_dtor_func(zval *zvalue ZEND_FILE_LINE_DC) } } break; + case IS_CONSTANT_AST: + ZEND_AST_DEL_REF(Z_AST_P(zvalue)); + break; case IS_OBJECT: { TSRMLS_FETCH(); @@ -81,6 +85,9 @@ ZEND_API void _zval_internal_dtor(zval *zvalue ZEND_FILE_LINE_DC) CHECK_ZVAL_STRING_REL(zvalue); str_free(zvalue->value.str.val); break; + case IS_CONSTANT_AST: + ZEND_AST_DEL_REF(Z_AST_P(zvalue)); + break; case IS_ARRAY: case IS_CONSTANT_ARRAY: case IS_OBJECT: @@ -139,6 +146,9 @@ ZEND_API void _zval_copy_ctor_func(zval *zvalue ZEND_FILE_LINE_DC) zvalue->value.ht = tmp_ht; } break; + case IS_CONSTANT_AST: + ZEND_AST_ADD_REF(Z_AST_P(zvalue)); + break; case IS_OBJECT: { TSRMLS_FETCH(); diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 572aac5a20..4ee5a99c7b 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -3252,12 +3252,16 @@ ZEND_VM_HANDLER(64, ZEND_RECV_INIT, ANY, CONST) if (param == NULL) { ALLOC_ZVAL(assignment_value); *assignment_value = *opline->op2.zv; - if ((Z_TYPE_P(assignment_value) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT || - Z_TYPE_P(assignment_value)==IS_CONSTANT_ARRAY) { - Z_SET_REFCOUNT_P(assignment_value, 1); - zval_update_constant(&assignment_value, 0 TSRMLS_CC); - } else { - zval_copy_ctor(assignment_value); + switch (Z_TYPE_P(assignment_value) & IS_CONSTANT_TYPE_MASK) { + case IS_CONSTANT: + case IS_CONSTANT_ARRAY: + case IS_CONSTANT_AST: + Z_SET_REFCOUNT_P(assignment_value, 1); + zval_update_constant(&assignment_value, 0 TSRMLS_CC); + break; + default: + zval_copy_ctor(assignment_value); + break; } INIT_PZVAL(assignment_value); } else { @@ -3580,13 +3584,16 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST) } if (EXPECTED(zend_hash_quick_find(&ce->constants_table, Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv)+1, Z_HASH_P(opline->op2.zv), (void **) &value) == SUCCESS)) { - if (Z_TYPE_PP(value) == IS_CONSTANT_ARRAY || - (Z_TYPE_PP(value) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) { - zend_class_entry *old_scope = EG(scope); - - EG(scope) = ce; - zval_update_constant(value, (void *) 1 TSRMLS_CC); - EG(scope) = old_scope; + switch (Z_TYPE_PP(value) & IS_CONSTANT_TYPE_MASK) { + case IS_CONSTANT: + case IS_CONSTANT_ARRAY: + case IS_CONSTANT_AST: { + zend_class_entry *old_scope = EG(scope); + + EG(scope) = ce; + zval_update_constant(value, (void *) 1 TSRMLS_CC); + EG(scope) = old_scope; + } } if (OP1_TYPE == IS_CONST) { CACHE_PTR(opline->op2.literal->cache_slot, value); @@ -5187,20 +5194,27 @@ ZEND_VM_HANDLER(143, ZEND_DECLARE_CONST, CONST, CONST) name = GET_OP1_ZVAL_PTR(BP_VAR_R); val = GET_OP2_ZVAL_PTR(BP_VAR_R); - if ((Z_TYPE_P(val) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT || Z_TYPE_P(val) == IS_CONSTANT_ARRAY) { - zval tmp; - zval *tmp_ptr = &tmp; + switch (Z_TYPE_P(val) & IS_CONSTANT_TYPE_MASK) { + case IS_CONSTANT: + case IS_CONSTANT_ARRAY: + case IS_CONSTANT_AST: { + zval tmp; + zval *tmp_ptr = &tmp; - ZVAL_COPY_VALUE(&tmp, val); - if (Z_TYPE_P(val) == IS_CONSTANT_ARRAY) { - zval_copy_ctor(&tmp); + ZVAL_COPY_VALUE(&tmp, val); + if (Z_TYPE_P(val) == IS_CONSTANT_ARRAY) { + zval_copy_ctor(&tmp); + } + INIT_PZVAL(&tmp); + zval_update_constant(&tmp_ptr, NULL TSRMLS_CC); + c.value = *tmp_ptr; } - INIT_PZVAL(&tmp); - zval_update_constant(&tmp_ptr, NULL TSRMLS_CC); - c.value = *tmp_ptr; - } else { - INIT_PZVAL_COPY(&c.value, val); - zval_copy_ctor(&c.value); + break; + + default: + INIT_PZVAL_COPY(&c.value, val); + zval_copy_ctor(&c.value); + break; } c.flags = CONST_CS; /* non persistent, case sensetive */ c.name = str_strndup(Z_STRVAL_P(name), Z_STRLEN_P(name)); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 869bb199b2..a90f187fef 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -1435,12 +1435,16 @@ static int ZEND_FASTCALL ZEND_RECV_INIT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ if (param == NULL) { ALLOC_ZVAL(assignment_value); *assignment_value = *opline->op2.zv; - if ((Z_TYPE_P(assignment_value) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT || - Z_TYPE_P(assignment_value)==IS_CONSTANT_ARRAY) { - Z_SET_REFCOUNT_P(assignment_value, 1); - zval_update_constant(&assignment_value, 0 TSRMLS_CC); - } else { - zval_copy_ctor(assignment_value); + switch (Z_TYPE_P(assignment_value) & IS_CONSTANT_TYPE_MASK) { + case IS_CONSTANT: + case IS_CONSTANT_ARRAY: + case IS_CONSTANT_AST: + Z_SET_REFCOUNT_P(assignment_value, 1); + zval_update_constant(&assignment_value, 0 TSRMLS_CC); + break; + default: + zval_copy_ctor(assignment_value); + break; } INIT_PZVAL(assignment_value); } else { @@ -3792,13 +3796,16 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCO } if (EXPECTED(zend_hash_quick_find(&ce->constants_table, Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv)+1, Z_HASH_P(opline->op2.zv), (void **) &value) == SUCCESS)) { - if (Z_TYPE_PP(value) == IS_CONSTANT_ARRAY || - (Z_TYPE_PP(value) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) { - zend_class_entry *old_scope = EG(scope); + switch (Z_TYPE_PP(value) & IS_CONSTANT_TYPE_MASK) { + case IS_CONSTANT: + case IS_CONSTANT_ARRAY: + case IS_CONSTANT_AST: { + zend_class_entry *old_scope = EG(scope); - EG(scope) = ce; - zval_update_constant(value, (void *) 1 TSRMLS_CC); - EG(scope) = old_scope; + EG(scope) = ce; + zval_update_constant(value, (void *) 1 TSRMLS_CC); + EG(scope) = old_scope; + } } if (IS_CONST == IS_CONST) { CACHE_PTR(opline->op2.literal->cache_slot, value); @@ -4089,20 +4096,27 @@ static int ZEND_FASTCALL ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER(ZEND_OPCOD name = opline->op1.zv; val = opline->op2.zv; - if ((Z_TYPE_P(val) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT || Z_TYPE_P(val) == IS_CONSTANT_ARRAY) { - zval tmp; - zval *tmp_ptr = &tmp; + switch (Z_TYPE_P(val) & IS_CONSTANT_TYPE_MASK) { + case IS_CONSTANT: + case IS_CONSTANT_ARRAY: + case IS_CONSTANT_AST: { + zval tmp; + zval *tmp_ptr = &tmp; - ZVAL_COPY_VALUE(&tmp, val); - if (Z_TYPE_P(val) == IS_CONSTANT_ARRAY) { - zval_copy_ctor(&tmp); + ZVAL_COPY_VALUE(&tmp, val); + if (Z_TYPE_P(val) == IS_CONSTANT_ARRAY) { + zval_copy_ctor(&tmp); + } + INIT_PZVAL(&tmp); + zval_update_constant(&tmp_ptr, NULL TSRMLS_CC); + c.value = *tmp_ptr; } - INIT_PZVAL(&tmp); - zval_update_constant(&tmp_ptr, NULL TSRMLS_CC); - c.value = *tmp_ptr; - } else { - INIT_PZVAL_COPY(&c.value, val); - zval_copy_ctor(&c.value); + break; + + default: + INIT_PZVAL_COPY(&c.value, val); + zval_copy_ctor(&c.value); + break; } c.flags = CONST_CS; /* non persistent, case sensetive */ c.name = str_strndup(Z_STRVAL_P(name), Z_STRLEN_P(name)); @@ -15635,13 +15649,16 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE } if (EXPECTED(zend_hash_quick_find(&ce->constants_table, Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv)+1, Z_HASH_P(opline->op2.zv), (void **) &value) == SUCCESS)) { - if (Z_TYPE_PP(value) == IS_CONSTANT_ARRAY || - (Z_TYPE_PP(value) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) { - zend_class_entry *old_scope = EG(scope); + switch (Z_TYPE_PP(value) & IS_CONSTANT_TYPE_MASK) { + case IS_CONSTANT: + case IS_CONSTANT_ARRAY: + case IS_CONSTANT_AST: { + zend_class_entry *old_scope = EG(scope); - EG(scope) = ce; - zval_update_constant(value, (void *) 1 TSRMLS_CC); - EG(scope) = old_scope; + EG(scope) = ce; + zval_update_constant(value, (void *) 1 TSRMLS_CC); + EG(scope) = old_scope; + } } if (IS_VAR == IS_CONST) { CACHE_PTR(opline->op2.literal->cache_slot, value); @@ -25171,13 +25188,16 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPC } if (EXPECTED(zend_hash_quick_find(&ce->constants_table, Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv)+1, Z_HASH_P(opline->op2.zv), (void **) &value) == SUCCESS)) { - if (Z_TYPE_PP(value) == IS_CONSTANT_ARRAY || - (Z_TYPE_PP(value) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) { - zend_class_entry *old_scope = EG(scope); + switch (Z_TYPE_PP(value) & IS_CONSTANT_TYPE_MASK) { + case IS_CONSTANT: + case IS_CONSTANT_ARRAY: + case IS_CONSTANT_AST: { + zend_class_entry *old_scope = EG(scope); - EG(scope) = ce; - zval_update_constant(value, (void *) 1 TSRMLS_CC); - EG(scope) = old_scope; + EG(scope) = ce; + zval_update_constant(value, (void *) 1 TSRMLS_CC); + EG(scope) = old_scope; + } } if (IS_UNUSED == IS_CONST) { CACHE_PTR(opline->op2.literal->cache_slot, value); |