summaryrefslogtreecommitdiff
path: root/Zend/zend_compile.c
diff options
context:
space:
mode:
Diffstat (limited to 'Zend/zend_compile.c')
-rw-r--r--Zend/zend_compile.c41
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;
- }
}
}
/* }}} */