diff options
Diffstat (limited to 'Zend/zend_compile.c')
-rw-r--r-- | Zend/zend_compile.c | 41 |
1 files changed, 28 insertions, 13 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 65538094b7..1e38cafc89 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -97,6 +97,12 @@ static void zend_destroy_property_info_internal(zval *zv) /* {{{ */ } /* }}} */ +static void zend_destroy_class_constant_internal(zval *zv) /* {{{ */ +{ + free(Z_PTR_P(zv)); +} +/* }}} */ + static zend_string *zend_new_interned_string_safe(zend_string *str) /* {{{ */ { zend_string *interned_str; @@ -1437,14 +1443,15 @@ static zend_bool zend_try_compile_const_expr_resolve_class_name(zval *zv, zend_a 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); + zend_class_constant *cc; zval *c; if (class_name_refers_to_active_ce(class_name, fetch_type)) { - c = zend_hash_find(&CG(active_class_entry)->constants_table, name); + cc = zend_hash_find_ptr(&CG(active_class_entry)->constants_table, name); } else if (fetch_type == ZEND_FETCH_CLASS_DEFAULT && !(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION)) { zend_class_entry *ce = zend_hash_find_ptr_lc(CG(class_table), ZSTR_VAL(class_name), ZSTR_LEN(class_name)); if (ce) { - c = zend_hash_find(&ce->constants_table, name); + cc = zend_hash_find_ptr(&ce->constants_table, name); } else { return 0; } @@ -1456,8 +1463,14 @@ static zend_bool zend_try_ct_eval_class_const(zval *zv, zend_string *class_name, return 0; } + if (!cc || !zend_verify_const_access(cc, CG(active_class_entry))) { + return 0; + } + + c = &cc->value; + /* Substitute case-sensitive (or lowercase) persistent class constants */ - if (c && Z_TYPE_P(c) < IS_OBJECT) { + if (Z_TYPE_P(c) < IS_OBJECT) { ZVAL_DUP(zv, c); return 1; } @@ -1638,7 +1651,6 @@ again: ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify_handlers) /* {{{ */ { zend_bool persistent_hashes = (ce->type == ZEND_INTERNAL_CLASS) ? 1 : 0; - dtor_func_t zval_ptr_dtor_func = ((persistent_hashes) ? ZVAL_INTERNAL_PTR_DTOR : ZVAL_PTR_DTOR); ce->refcount = 1; ce->ce_flags = ZEND_ACC_CONSTANTS_UPDATED; @@ -1650,7 +1662,7 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify ce->default_properties_table = NULL; ce->default_static_members_table = NULL; zend_hash_init_ex(&ce->properties_info, 8, NULL, (persistent_hashes ? zend_destroy_property_info_internal : NULL), persistent_hashes, 0); - zend_hash_init_ex(&ce->constants_table, 8, NULL, zval_ptr_dtor_func, persistent_hashes, 0); + zend_hash_init_ex(&ce->constants_table, 8, NULL, (persistent_hashes ? zend_destroy_class_constant_internal : NULL), persistent_hashes, 0); zend_hash_init_ex(&ce->function_table, 8, NULL, ZEND_FUNCTION_DTOR, persistent_hashes, 0); if (ce->type == ZEND_INTERNAL_CLASS) { @@ -5183,25 +5195,28 @@ void zend_compile_class_const_decl(zend_ast *ast) /* {{{ */ zend_ast *const_ast = list->child[i]; zend_ast *name_ast = const_ast->child[0]; zend_ast *value_ast = const_ast->child[1]; + zend_ast *doc_comment_ast = const_ast->child[2]; zend_string *name = zend_ast_get_str(name_ast); + zend_string *doc_comment = doc_comment_ast ? zend_string_copy(zend_ast_get_str(doc_comment_ast)) : NULL; 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"); + if (UNEXPECTED(ast->attr & (ZEND_ACC_STATIC|ZEND_ACC_ABSTRACT|ZEND_ACC_FINAL))) { + if (ast->attr & ZEND_ACC_STATIC) { + zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'static' as constant modifier"); + } else if (ast->attr & ZEND_ACC_ABSTRACT) { + zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'abstract' as constant modifier"); + } else if (ast->attr & ZEND_ACC_FINAL) { + zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'final' as constant modifier"); + } } zend_const_expr_to_zval(&value_zv, value_ast); name = zend_new_interned_string_safe(name); - if (zend_hash_add(&ce->constants_table, name, &value_zv) == NULL) { + if (zend_declare_class_constant_ex(ce, name, &value_zv, ast->attr, doc_comment) != SUCCESS) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot redefine class constant %s::%s", ZSTR_VAL(ce->name), ZSTR_VAL(name)); } - - if (Z_CONSTANT(value_zv)) { - ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED; - } } } /* }}} */ |