From 4ecc52797650c882f3101edd7171007ac0d15ec7 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 7 May 2014 03:26:13 +0400 Subject: [PATCH] Reverted Bob's patch (it breaks many tests when run with opcache and needs to be fixed first). --- Zend/tests/bug66015.phpt | 7 +- Zend/tests/errmsg_040.phpt | 2 - Zend/tests/ns_059.phpt | 2 - Zend/zend_API.c | 1 + Zend/zend_ast.c | 38 +------ Zend/zend_ast.h | 3 - Zend/zend_compile.c | 84 ++++++++++----- Zend/zend_compile.h | 2 +- Zend/zend_execute_API.c | 118 ++++++++++++++++++++++ Zend/zend_language_parser.y | 18 ++-- Zend/zend_types.h | 16 +-- Zend/zend_variables.c | 15 ++- Zend/zend_vm_def.h | 3 + Zend/zend_vm_execute.h | 3 + ext/opcache/zend_accelerator_util_funcs.c | 4 - ext/opcache/zend_persist.c | 2 - ext/opcache/zend_persist_calc.c | 2 - 17 files changed, 212 insertions(+), 108 deletions(-) diff --git a/Zend/tests/bug66015.phpt b/Zend/tests/bug66015.phpt index 99003e6045..4f6d51e0dd 100644 --- a/Zend/tests/bug66015.phpt +++ b/Zend/tests/bug66015.phpt @@ -11,8 +11,7 @@ class Test protected static $array = [ self::FIRST => 'first', 'second', - 'third', - 4, + 'third' ]; public function __construct() @@ -23,13 +22,9 @@ class Test $test = new Test(); ?> - -===DONE=== --EXPECTF-- array ( 1 => 'first', 2 => 'second', 3 => 'third', - 4 => 4, ) -===DONE=== diff --git a/Zend/tests/errmsg_040.phpt b/Zend/tests/errmsg_040.phpt index 2b192d0b83..f3d0afcf0a 100644 --- a/Zend/tests/errmsg_040.phpt +++ b/Zend/tests/errmsg_040.phpt @@ -1,7 +1,5 @@ --TEST-- errmsg: arrays are not allowed in class constants ---XFAIL-- -Actually it's hard to test where the array comes from (property, constant, ...) --FILE-- type & ZEND_INTERNAL_CLASS) { switch(Z_TYPE_P(property)) { case IS_ARRAY: + case IS_CONSTANT_ARRAY: case IS_OBJECT: case IS_RESOURCE: zend_error(E_CORE_ERROR, "Internal zval's can't be arrays, objects or resources"); diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c index 7d22ea0f0f..07d38dc6bf 100644 --- a/Zend/zend_ast.c +++ b/Zend/zend_ast.c @@ -62,27 +62,6 @@ ZEND_API zend_ast* zend_ast_create_ternary(uint kind, zend_ast *op0, zend_ast *o return ast; } -ZEND_API zend_ast* zend_ast_create_dynamic(uint kind) -{ - zend_ast *ast = emalloc(sizeof(zend_ast) + sizeof(zend_ast*) * 3); /* use 4 children as deafult */ - ast->kind = kind; - ast->children = 0; - return ast; -} - -ZEND_API void zend_ast_dynamic_add(zend_ast **ast, zend_ast *op) -{ - if ((*ast)->children >= 4 && (*ast)->children == ((*ast)->children & -(*ast)->children)) { - *ast = erealloc(*ast, sizeof(zend_ast) + sizeof(zend_ast*) * ((*ast)->children * 2 + 1)); - } - (&(*ast)->u.child)[(*ast)->children++] = op; -} - -ZEND_API void zend_ast_dynamic_shrink(zend_ast **ast) -{ - *ast = erealloc(*ast, sizeof(zend_ast) + sizeof(zend_ast*) * ((*ast)->children - 1)); -} - ZEND_API int zend_ast_is_ct_constant(zend_ast *ast) { int i; @@ -303,21 +282,6 @@ ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *s sub_function(result, &op1, &op2 TSRMLS_CC); zval_dtor(&op2); break; - case ZEND_INIT_ARRAY: - array_init(result); - { - int i; - for (i = 0; i < ast->children; i+=2) { - if ((&ast->u.child)[i]) { - zend_ast_evaluate(&op1, (&ast->u.child)[i], scope TSRMLS_CC); - } else { - Z_TYPE_INFO(op1) = IS_UNDEF; - } - zend_ast_evaluate(&op2, (&ast->u.child)[i+1], scope TSRMLS_CC); - zend_do_add_static_array_element(*result, op1, op2 TSRMLS_CC); - } - } - break; default: zend_error(E_ERROR, "Unsupported constant expression"); } @@ -341,7 +305,7 @@ ZEND_API zend_ast *zend_ast_copy(zend_ast *ast) } return new; } - return zend_ast_create_dynamic(ast->kind); + return NULL; } ZEND_API void zend_ast_destroy(zend_ast *ast) diff --git a/Zend/zend_ast.h b/Zend/zend_ast.h index 8678299f0f..cac3a54dd4 100644 --- a/Zend/zend_ast.h +++ b/Zend/zend_ast.h @@ -48,9 +48,6 @@ ZEND_API zend_ast *zend_ast_create_constant(zval *zv); ZEND_API zend_ast *zend_ast_create_unary(uint kind, zend_ast *op0); ZEND_API zend_ast *zend_ast_create_binary(uint kind, zend_ast *op0, zend_ast *op1); ZEND_API zend_ast *zend_ast_create_ternary(uint kind, zend_ast *op0, zend_ast *op1, zend_ast *op2); -ZEND_API zend_ast* zend_ast_create_dynamic(uint kind); -ZEND_API void zend_ast_dynamic_add(zend_ast **ast, zend_ast *op); -ZEND_API void zend_ast_dynamic_shrink(zend_ast **ast); ZEND_API int zend_ast_is_ct_constant(zend_ast *ast); diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 7d33954501..de62e9c439 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1910,7 +1910,7 @@ void zend_do_receive_param(zend_uchar op, znode *varname, znode *initialization, 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")) || Z_TYPE(initialization->u.constant) == IS_CONSTANT_AST) { cur_arg_info->allow_null = 1; - } else if (Z_TYPE(initialization->u.constant) != IS_ARRAY) { + } 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"); } } @@ -5462,6 +5462,10 @@ void zend_do_declare_class_constant(znode *var_name, znode *value TSRMLS_DC) /* { zval property; + if(Z_TYPE(value->u.constant) == IS_CONSTANT_ARRAY) { + zend_error_noreturn(E_COMPILE_ERROR, "Arrays are not allowed in class constants"); + return; + } if ((CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) { zend_error_noreturn(E_COMPILE_ERROR, "Traits cannot have constants"); return; @@ -5910,34 +5914,54 @@ void zend_do_end_array(znode *result, const znode *array_node TSRMLS_DC) /* {{{ } /* }}} */ -void zend_do_add_static_array_element(zval result, zval offset, zval expr TSRMLS_DC) /* {{{ */ +void zend_do_add_static_array_element(znode *result, znode *offset, znode *expr TSRMLS_DC) /* {{{ */ { - switch (Z_TYPE(offset)) { - case IS_UNDEF: - zend_hash_next_index_insert(Z_ARRVAL(result), &expr); - break; - case IS_STRING: - zend_symtable_update(Z_ARRVAL(result), Z_STR(offset), &expr); - zval_dtor(&offset); - break; - case IS_NULL: - zend_symtable_update(Z_ARRVAL(result), STR_EMPTY_ALLOC(), &expr); - break; - case IS_LONG: - zend_hash_index_update(Z_ARRVAL(result), Z_LVAL(offset), &expr); - break; - case IS_FALSE: - zend_hash_index_update(Z_ARRVAL(result), 0, &expr); - break; - case IS_TRUE: - zend_hash_index_update(Z_ARRVAL(result), 1, &expr); - break; - case IS_DOUBLE: - zend_hash_index_update(Z_ARRVAL(result), zend_dval_to_lval(Z_DVAL(offset)), &expr); - break; - case IS_ARRAY: - zend_error(E_ERROR, "Illegal offset type"); - break; + zval element; + + ZVAL_COPY_VALUE(&element, &expr->u.constant); + if (offset) { + switch (Z_TYPE(offset->u.constant)) { + case IS_CONSTANT: + Z_GC_FLAGS(offset->u.constant) |= IS_STR_CONSTANT; + if (Z_CONST_FLAGS(offset->u.constant) & IS_CONSTANT_UNQUALIFIED) { + Z_GC_FLAGS(offset->u.constant) |= IS_STR_CONSTANT_UNQUALIFIED; + } + zend_symtable_update(Z_ARRVAL(result->u.constant), Z_STR(offset->u.constant), &element); + zval_dtor(&offset->u.constant); + break; + case IS_CONSTANT_AST: { + zend_string *key; + key = STR_INIT((char*)&Z_AST(offset->u.constant), sizeof(zend_ast*), 0); + GC_FLAGS(key) |= IS_STR_AST; + zend_symtable_update(Z_ARRVAL(result->u.constant), key, &element); + STR_RELEASE(key); + break; + } + case IS_STRING: + zend_symtable_update(Z_ARRVAL(result->u.constant), Z_STR(offset->u.constant), &element); + zval_dtor(&offset->u.constant); + break; + case IS_NULL: + zend_symtable_update(Z_ARRVAL(result->u.constant), STR_EMPTY_ALLOC(), &element); + break; + case IS_LONG: + zend_hash_index_update(Z_ARRVAL(result->u.constant), Z_LVAL(offset->u.constant), &element); + break; + case IS_FALSE: + zend_hash_index_update(Z_ARRVAL(result->u.constant), 0, &element); + break; + case IS_TRUE: + zend_hash_index_update(Z_ARRVAL(result->u.constant), 1, &element); + break; + case IS_DOUBLE: + zend_hash_index_update(Z_ARRVAL(result->u.constant), zend_dval_to_lval(Z_DVAL(offset->u.constant)), &element); + break; + case IS_CONSTANT_ARRAY: + zend_error(E_ERROR, "Illegal offset type"); + break; + } + } else { + zend_hash_next_index_insert(Z_ARRVAL(result->u.constant), &element); } } /* }}} */ @@ -7299,6 +7323,10 @@ void zend_do_declare_constant(znode *name, znode *value TSRMLS_DC) /* {{{ */ zend_op *opline; zval *ns_name; + if(Z_TYPE(value->u.constant) == IS_CONSTANT_ARRAY) { + zend_error_noreturn(E_COMPILE_ERROR, "Arrays are not allowed as constants"); + } + if (zend_get_ct_const(&name->u.constant, 0 TSRMLS_CC)) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare constant '%s'", Z_STRVAL(name->u.constant)); } diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 39d6dff109..4288a3b705 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -587,7 +587,7 @@ void zend_do_shell_exec(znode *result, znode *cmd TSRMLS_DC); void zend_do_init_array(znode *result, znode *expr, znode *offset, zend_bool is_ref TSRMLS_DC); void zend_do_add_array_element(znode *result, znode *expr, znode *offset, zend_bool is_ref TSRMLS_DC); void zend_do_end_array(znode *result, const znode *array_node TSRMLS_DC); -void zend_do_add_static_array_element(zval result, zval offset, zval expr TSRMLS_DC); +void zend_do_add_static_array_element(znode *result, znode *offset, znode *expr TSRMLS_DC); void zend_do_list_init(TSRMLS_D); void zend_do_list_end(znode *result, znode *expr TSRMLS_DC); void zend_do_add_list_element(const znode *element TSRMLS_DC); diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 15f79738e6..3806af0a05 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -592,6 +592,124 @@ ZEND_API int zval_update_constant_ex(zval *p, zend_bool inline_change, zend_clas } if (Z_REFCOUNTED_P(p)) Z_SET_REFCOUNT_P(p, refcount); + } else if (Z_TYPE_P(p) == IS_CONSTANT_ARRAY) { + zval *element, new_val; + zend_string *str_index; + ulong num_index; + int ret; + + SEPARATE_ZVAL_IF_NOT_REF(p); + + Z_TYPE_INFO_P(p) = IS_ARRAY_EX; + if (!inline_change) { + HashTable *ht = Z_ARRVAL_P(p); + ZVAL_NEW_ARR(p); + zend_hash_init(Z_ARRVAL_P(p), zend_hash_num_elements(ht), NULL, ZVAL_PTR_DTOR, 0); + zend_hash_copy(Z_ARRVAL_P(p), ht, ZVAL_COPY_CTOR); + } + + /* First go over the array and see if there are any constant indices */ + zend_hash_internal_pointer_reset(Z_ARRVAL_P(p)); + while ((element = zend_hash_get_current_data(Z_ARRVAL_P(p))) != NULL) { + if (zend_hash_get_current_key(Z_ARRVAL_P(p), &str_index, &num_index, 0) != HASH_KEY_IS_STRING) { + zend_hash_move_forward(Z_ARRVAL_P(p)); + continue; + } + if (!(GC_FLAGS(str_index) & (IS_STR_CONSTANT | IS_STR_AST))) { + zend_hash_move_forward(Z_ARRVAL_P(p)); + continue; + } + + if (GC_FLAGS(str_index) & IS_STR_AST) { + zend_ast_ref *ast = *(zend_ast_ref **)str_index->val; + + zend_ast_evaluate(&tmp, ast->ast, scope TSRMLS_CC); + zend_ast_destroy(ast->ast); + efree(ast); + const_value = &tmp; + } else if (!(const_value = zend_get_constant_ex(str_index, scope, GC_FLAGS(str_index) & ~(IS_STR_PERSISTENT | IS_STR_INTERNED |IS_STR_PERMANENT) TSRMLS_CC))) { + char *actual, *str; + const char *save = str_index->val; + int len; + + str = str_index->val; + len = str_index->len; + if ((colon = (char*)zend_memrchr(str, ':', len))) { + zend_error(E_ERROR, "Undefined class constant '%s'", str); + len -= ((colon - str) + 1); + str = colon; + } else { + if (GC_FLAGS(str_index) & IS_STR_CONSTANT_UNQUALIFIED) { + if ((actual = (char *)zend_memrchr(str, '\\', len))) { + actual++; + len -= (actual - str); + str = actual; + } + } + if (str[0] == '\\') { + ++str; + --len; + } + if (save[0] == '\\') { + ++save; + } + if (!(GC_FLAGS(str_index) & IS_STR_CONSTANT_UNQUALIFIED)) { + zend_error(E_ERROR, "Undefined constant '%s'", save); + } + zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", str, str); + } + if (str == str_index->val && len == str_index->len) { + ZVAL_STR(&tmp, STR_COPY(str_index)); + } else { + ZVAL_STRINGL(&tmp, str, len); + } + const_value = &tmp; + } else { +//???! + ZVAL_COPY_VALUE(&tmp, const_value); + if (Z_OPT_CONSTANT(tmp)) { + zval_update_constant_ex(&tmp, 1, NULL TSRMLS_CC); + } + zval_opt_copy_ctor(&tmp); + const_value = &tmp; + } + + if (Z_REFCOUNTED_P(element) && Z_REFCOUNT_P(element) > 1) { + ZVAL_DUP(&new_val, element); + zval_ptr_dtor(element); + ZVAL_COPY_VALUE(element, &new_val); + } + + switch (Z_TYPE_P(const_value)) { + case IS_STRING: + ret = zend_symtable_update_current_key_ex(Z_ARRVAL_P(p), Z_STR_P(const_value), HASH_UPDATE_KEY_IF_BEFORE); + break; + case IS_FALSE: + ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL, 0, HASH_UPDATE_KEY_IF_BEFORE); + break; + case IS_TRUE: + ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL, 1, HASH_UPDATE_KEY_IF_BEFORE); + break; + case IS_LONG: + ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL, Z_LVAL_P(const_value), HASH_UPDATE_KEY_IF_BEFORE); + break; + case IS_DOUBLE: + ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL, zend_dval_to_lval(Z_DVAL_P(const_value)), HASH_UPDATE_KEY_IF_BEFORE); + break; + case IS_NULL: + ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_STRING, STR_EMPTY_ALLOC(), 0, HASH_UPDATE_KEY_IF_BEFORE); + break; + default: + ret = SUCCESS; + break; + } + if (ret == SUCCESS) { + zend_hash_move_forward(Z_ARRVAL_P(p)); + } + 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)); } else if (Z_TYPE_P(p) == IS_CONSTANT_AST) { SEPARATE_ZVAL_IF_NOT_REF(p); diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index 43e20cd9ce..6f39f4d63f 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -986,7 +986,9 @@ static_class_constant: ; static_scalar: /* compile-time evaluated scalars */ - static_scalar_value { zend_do_constant_expression(&$$, $1.u.ast TSRMLS_CC); } + static_scalar_value { zend_do_constant_expression(&$$, $1.u.ast TSRMLS_CC); } + | T_ARRAY '(' static_array_pair_list ')' { $$ = $3; Z_TYPE_INFO($$.u.constant) = IS_CONSTANT_ARRAY_EX; } + | '[' static_array_pair_list ']' { $$ = $2; Z_TYPE_INFO($$.u.constant) = IS_CONSTANT_ARRAY_EX; } ; static_scalar_value: @@ -995,8 +997,6 @@ static_scalar_value: | namespace_name { zend_do_fetch_constant(&$$, NULL, &$1, ZEND_CT, 1 TSRMLS_CC); $$.u.ast = zend_ast_create_constant(&$$.u.constant); } | 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); $$.u.ast = zend_ast_create_constant(&$$.u.constant); } | T_NS_SEPARATOR namespace_name { zval tmp; ZVAL_NEW_STR(&tmp, STR_ALLOC(Z_STRLEN($2.u.constant)+1, 0)); Z_STRVAL(tmp)[0] = '\\'; memcpy(Z_STRVAL(tmp) + 1, Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); if (Z_DELREF($2.u.constant) == 0) {efree(Z_STR($2.u.constant));} Z_STR($2.u.constant) = Z_STR(tmp); zend_do_fetch_constant(&$$, NULL, &$2, ZEND_CT, 0 TSRMLS_CC); $$.u.ast = zend_ast_create_constant(&$$.u.constant); } - | T_ARRAY '(' static_array_pair_list ')' { $$ = $3; } - | '[' static_array_pair_list ']' { $$ = $2; } | static_class_constant { $$.u.ast = zend_ast_create_constant(&$1.u.constant); } | T_CLASS_C { $$.u.ast = zend_ast_create_constant(&$1.u.constant); } | static_operation { $$ = $1; } @@ -1053,8 +1053,8 @@ scalar: static_array_pair_list: - /* empty */ { $$.op_type = IS_CONST; array_init(&$$.u.constant); $$.u.ast = zend_ast_create_constant(&$$.u.constant); } - | non_empty_static_array_pair_list possible_comma { zend_ast_dynamic_shrink(&$1.u.ast); $$ = $1; } + /* empty */ { $$.op_type = IS_CONST; array_init(&$$.u.constant); } + | non_empty_static_array_pair_list possible_comma { $$ = $1; } ; possible_comma: @@ -1063,10 +1063,10 @@ possible_comma: ; non_empty_static_array_pair_list: - non_empty_static_array_pair_list ',' static_scalar_value T_DOUBLE_ARROW static_scalar_value { zend_ast_dynamic_add(&$$.u.ast, $3.u.ast); zend_ast_dynamic_add(&$$.u.ast, $5.u.ast); } - | non_empty_static_array_pair_list ',' static_scalar_value { zend_ast_dynamic_add(&$$.u.ast, NULL); zend_ast_dynamic_add(&$$.u.ast, $3.u.ast); } - | static_scalar_value T_DOUBLE_ARROW static_scalar_value { $$.u.ast = zend_ast_create_dynamic(ZEND_INIT_ARRAY); zend_ast_dynamic_add(&$$.u.ast, $1.u.ast); zend_ast_dynamic_add(&$$.u.ast, $3.u.ast); } - | static_scalar_value { $$.u.ast = zend_ast_create_dynamic(ZEND_INIT_ARRAY); zend_ast_dynamic_add(&$$.u.ast, NULL); zend_ast_dynamic_add(&$$.u.ast, $1.u.ast); } + non_empty_static_array_pair_list ',' static_scalar T_DOUBLE_ARROW static_scalar { zend_do_add_static_array_element(&$$, &$3, &$5 TSRMLS_CC); } + | non_empty_static_array_pair_list ',' static_scalar { zend_do_add_static_array_element(&$$, NULL, &$3 TSRMLS_CC); } + | static_scalar T_DOUBLE_ARROW static_scalar { $$.op_type = IS_CONST; array_init(&$$.u.constant); zend_do_add_static_array_element(&$$, &$1, &$3 TSRMLS_CC); } + | static_scalar { $$.op_type = IS_CONST; array_init(&$$.u.constant); zend_do_add_static_array_element(&$$, NULL, &$1 TSRMLS_CC); } ; expr: diff --git a/Zend/zend_types.h b/Zend/zend_types.h index 211c44a944..3e3cc51b7e 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -212,20 +212,21 @@ struct _zend_ast_ref { #define IS_ARRAY 7 #define IS_OBJECT 8 #define IS_RESOURCE 9 -#define IS_REFERENCE 10 +#define IS_REFERENCE 10 /* constant expressions */ #define IS_CONSTANT 11 -#define IS_CONSTANT_AST 12 +#define IS_CONSTANT_ARRAY 12 +#define IS_CONSTANT_AST 13 /* fake types */ -#define _IS_BOOL 13 -#define IS_CALLABLE 14 +#define _IS_BOOL 14 +#define IS_CALLABLE 15 /* internal types */ -#define IS_INDIRECT 15 -#define IS_STR_OFFSET 16 -#define IS_PTR 17 +#define IS_INDIRECT 16 +#define IS_STR_OFFSET 17 +#define IS_PTR 18 static inline zend_uchar zval_get_type(const zval* pz) { return pz->u1.v.type; @@ -293,6 +294,7 @@ static inline zend_uchar zval_get_type(const zval* pz) { #define IS_REFERENCE_EX (IS_REFERENCE | (( IS_TYPE_REFCOUNTED ) << Z_TYPE_FLAGS_SHIFT)) #define IS_CONSTANT_EX (IS_CONSTANT | ((IS_TYPE_CONSTANT | IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE) << Z_TYPE_FLAGS_SHIFT)) +#define IS_CONSTANT_ARRAY_EX (IS_CONSTANT_ARRAY | ((IS_TYPE_CONSTANT | IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE) << Z_TYPE_FLAGS_SHIFT)) #define IS_CONSTANT_AST_EX (IS_CONSTANT_AST | ((IS_TYPE_CONSTANT | IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE) << Z_TYPE_FLAGS_SHIFT)) /* zval.u1.v.const_flags */ diff --git a/Zend/zend_variables.c b/Zend/zend_variables.c index 64bd1ae844..c05e404c06 100644 --- a/Zend/zend_variables.c +++ b/Zend/zend_variables.c @@ -37,9 +37,10 @@ ZEND_API void _zval_dtor_func(zend_refcounted *p ZEND_FILE_LINE_DC) STR_RELEASE(str); break; } - case IS_ARRAY: { + case IS_ARRAY: + case IS_CONSTANT_ARRAY: { + zend_array *arr =(zend_array*)p; TSRMLS_FETCH(); - zend_array *arr = (zend_array*)p; if (arr != &EG(symbol_table)) { /* break possible cycles */ @@ -51,7 +52,7 @@ ZEND_API void _zval_dtor_func(zend_refcounted *p ZEND_FILE_LINE_DC) break; } case IS_CONSTANT_AST: { - zend_ast_ref *ast = (zend_ast_ref*)p; + zend_ast_ref *ast =(zend_ast_ref*)p; zend_ast_destroy(ast->ast); efree(ast); @@ -97,7 +98,8 @@ ZEND_API void _zval_dtor_func_for_ptr(zend_refcounted *p ZEND_FILE_LINE_DC) STR_FREE(str); break; } - case IS_ARRAY: { + case IS_ARRAY: + case IS_CONSTANT_ARRAY: { zend_array *arr =(zend_array*)p; TSRMLS_FETCH(); @@ -153,6 +155,7 @@ ZEND_API void _zval_internal_dtor(zval *zvalue ZEND_FILE_LINE_DC) STR_RELEASE(Z_STR_P(zvalue)); break; case IS_ARRAY: + case IS_CONSTANT_ARRAY: case IS_CONSTANT_AST: case IS_OBJECT: case IS_RESOURCE: @@ -184,6 +187,7 @@ ZEND_API void _zval_internal_dtor_for_ptr(zval *zvalue ZEND_FILE_LINE_DC) STR_FREE(Z_STR_P(zvalue)); break; case IS_ARRAY: + case IS_CONSTANT_ARRAY: case IS_CONSTANT_AST: case IS_OBJECT: case IS_RESOURCE: @@ -236,7 +240,8 @@ ZEND_API void _zval_copy_ctor_func(zval *zvalue ZEND_FILE_LINE_DC) CHECK_ZVAL_STRING_REL(Z_STR_P(zvalue)); Z_STR_P(zvalue) = STR_DUP(Z_STR_P(zvalue), 0); break; - case IS_ARRAY: { + case IS_ARRAY: + case IS_CONSTANT_ARRAY: { HashTable *ht; TSRMLS_FETCH(); diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index afb569bdc2..64b44d0675 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -5275,6 +5275,9 @@ ZEND_VM_HANDLER(143, ZEND_DECLARE_CONST, CONST, CONST) ZVAL_COPY_VALUE(&c.value, val); if (Z_OPT_CONSTANT(c.value)) { + if (Z_TYPE_P(val) == IS_CONSTANT_ARRAY) { + zval_opt_copy_ctor(&c.value); + } zval_update_constant(&c.value, 0 TSRMLS_CC); } else { /* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */ diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index d4d58b1bdd..96bbc226e2 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -4221,6 +4221,9 @@ static int ZEND_FASTCALL ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER(ZEND_OPCOD ZVAL_COPY_VALUE(&c.value, val); if (Z_OPT_CONSTANT(c.value)) { + if (Z_TYPE_P(val) == IS_CONSTANT_ARRAY) { + zval_opt_copy_ctor(&c.value); + } zval_update_constant(&c.value, 0 TSRMLS_CC); } else { /* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */ diff --git a/ext/opcache/zend_accelerator_util_funcs.c b/ext/opcache/zend_accelerator_util_funcs.c index c77a4d0149..3c143de1c1 100644 --- a/ext/opcache/zend_accelerator_util_funcs.c +++ b/ext/opcache/zend_accelerator_util_funcs.c @@ -273,7 +273,6 @@ static inline void zend_clone_zval(zval *src, int bind TSRMLS_DC) Z_STR_P(src) = zend_clone_str(Z_STR_P(src) TSRMLS_CC); break; case IS_ARRAY: -#if ZEND_EXTENSION_API_NO <= PHP_5_5_X_API_NO case IS_CONSTANT_ARRAY: if (Z_ARR_P(src) != &EG(symbol_table)) { if (bind && Z_REFCOUNT_P(src) > 1 && (ptr = accel_xlat_get(Z_ARR_P(src))) != NULL) { @@ -290,7 +289,6 @@ static inline void zend_clone_zval(zval *src, int bind TSRMLS_DC) } } break; -#endif case IS_REFERENCE: if (bind && Z_REFCOUNT_P(src) > 1 && (ptr = accel_xlat_get(Z_REF_P(src))) != NULL) { Z_REF_P(src) = ptr; @@ -304,7 +302,6 @@ static inline void zend_clone_zval(zval *src, int bind TSRMLS_DC) zend_clone_zval(Z_REFVAL_P(src), bind TSRMLS_CC); } break; -#if ZEND_EXTENSION_API_NO > PHP_5_5_X_API_NO case IS_CONSTANT_AST: if (bind && Z_REFCOUNT_P(src) > 1 && (ptr = accel_xlat_get(Z_AST_P(src))) != NULL) { Z_AST_P(src) = ptr; @@ -319,7 +316,6 @@ static inline void zend_clone_zval(zval *src, int bind TSRMLS_DC) Z_ASTVAL_P(src) = zend_ast_clone(Z_ASTVAL_P(src) TSRMLS_CC); } break; -#endif } } diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index 30818adb30..33a99ee9c0 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -140,9 +140,7 @@ static void zend_persist_zval(zval *z TSRMLS_DC) Z_GC_FLAGS_P(z) |= flags; break; case IS_ARRAY: -#if ZEND_EXTENSION_API_NO <= PHP_5_5_API_NO case IS_CONSTANT_ARRAY: -#endif new_ptr = zend_shared_alloc_get_xlat_entry(Z_ARR_P(z)); if (new_ptr) { Z_ARR_P(z) = new_ptr; diff --git a/ext/opcache/zend_persist_calc.c b/ext/opcache/zend_persist_calc.c index b6740db044..a347a34cf3 100644 --- a/ext/opcache/zend_persist_calc.c +++ b/ext/opcache/zend_persist_calc.c @@ -127,9 +127,7 @@ static uint zend_persist_zval_calc(zval *z TSRMLS_DC) Z_GC_FLAGS_P(z) |= flags; break; case IS_ARRAY: -#if ZEND_EXTENSION_API_NO <= PHP_5_5_API_NO case IS_CONSTANT_ARRAY: -#endif size = zend_shared_memdup_size(Z_ARR_P(z), sizeof(zend_array)); if (size) { ADD_SIZE(size); -- 2.40.0