summaryrefslogtreecommitdiff
path: root/Zend/zend_constants.c
diff options
context:
space:
mode:
Diffstat (limited to 'Zend/zend_constants.c')
-rw-r--r--Zend/zend_constants.c99
1 files changed, 54 insertions, 45 deletions
diff --git a/Zend/zend_constants.c b/Zend/zend_constants.c
index 168c23a850..3e09f0cbb8 100644
--- a/Zend/zend_constants.c
+++ b/Zend/zend_constants.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| Zend Engine |
+----------------------------------------------------------------------+
- | Copyright (c) 1998-2015 Zend Technologies Ltd. (http://www.zend.com) |
+ | Copyright (c) 1998-2016 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 |
@@ -33,7 +33,7 @@ void free_zend_constant(zval *zv)
zend_constant *c = Z_PTR_P(zv);
if (!(c->flags & CONST_PERSISTENT)) {
- zval_dtor(&c->value);
+ zval_ptr_dtor(&c->value);
} else {
zval_internal_dtor(&c->value);
}
@@ -251,6 +251,18 @@ static zend_constant *zend_get_special_constant(const char *name, size_t name_le
}
}
+ZEND_API int zend_verify_const_access(zend_class_constant *c, zend_class_entry *scope) /* {{{ */
+{
+ if (Z_ACCESS_FLAGS(c->value) & ZEND_ACC_PUBLIC) {
+ return 1;
+ } else if (Z_ACCESS_FLAGS(c->value) & ZEND_ACC_PRIVATE) {
+ return (c->ce == scope);
+ } else {
+ ZEND_ASSERT(Z_ACCESS_FLAGS(c->value) & ZEND_ACC_PROTECTED);
+ return zend_check_protected(c->ce, scope);
+ }
+}
+/* }}} */
ZEND_API zval *zend_get_constant_str(const char *name, size_t name_len)
{
@@ -294,12 +306,11 @@ ZEND_API zval *zend_get_constant(zend_string *name)
return c ? &c->value : NULL;
}
-ZEND_API zval *zend_get_constant_ex(zend_string *cname, zend_class_entry *scope, zend_ulong flags)
+ZEND_API zval *zend_get_constant_ex(zend_string *cname, zend_class_entry *scope, uint32_t flags)
{
zend_constant *c;
const char *colon;
zend_class_entry *ce = NULL;
- zend_string *class_name;
const char *name = ZSTR_VAL(cname);
size_t name_len = ZSTR_LEN(cname);
@@ -315,70 +326,68 @@ ZEND_API zval *zend_get_constant_ex(zend_string *cname, zend_class_entry *scope,
int class_name_len = colon - name - 1;
size_t const_name_len = name_len - class_name_len - 2;
zend_string *constant_name = zend_string_init(colon + 1, const_name_len, 0);
- char *lcname;
+ zend_string *class_name = zend_string_init(name, class_name_len, 0);
zval *ret_constant = NULL;
- ALLOCA_FLAG(use_heap)
-
- class_name = zend_string_init(name, class_name_len, 0);
- lcname = do_alloca(class_name_len + 1, use_heap);
- zend_str_tolower_copy(lcname, name, class_name_len);
- if (!scope) {
- if (EG(current_execute_data)) {
- scope = EG(scope);
- } else {
- scope = CG(active_class_entry);
- }
- }
- if (class_name_len == sizeof("self")-1 &&
- !memcmp(lcname, "self", sizeof("self")-1)) {
+ if (zend_string_equals_literal_ci(class_name, "self")) {
if (UNEXPECTED(!scope)) {
- zend_throw_error(zend_ce_error, "Cannot access self:: when no class scope is active");
- return NULL;
+ zend_throw_error(NULL, "Cannot access self:: when no class scope is active");
+ goto failure;
}
ce = scope;
- } else if (class_name_len == sizeof("parent")-1 &&
- !memcmp(lcname, "parent", sizeof("parent")-1)) {
+ } else if (zend_string_equals_literal_ci(class_name, "parent")) {
if (UNEXPECTED(!scope)) {
- zend_throw_error(zend_ce_error, "Cannot access parent:: when no class scope is active");
- return NULL;
+ zend_throw_error(NULL, "Cannot access parent:: when no class scope is active");
+ goto failure;
} else if (UNEXPECTED(!scope->parent)) {
- zend_throw_error(zend_ce_error, "Cannot access parent:: when current class scope has no parent");
- return NULL;
+ zend_throw_error(NULL, "Cannot access parent:: when current class scope has no parent");
+ goto failure;
} else {
ce = scope->parent;
}
- } else if (class_name_len == sizeof("static")-1 &&
- !memcmp(lcname, "static", sizeof("static")-1)) {
+ } else if (zend_string_equals_literal_ci(class_name, "static")) {
ce = zend_get_called_scope(EG(current_execute_data));
if (UNEXPECTED(!ce)) {
- zend_throw_error(zend_ce_error, "Cannot access static:: when no class scope is active");
- return NULL;
+ zend_throw_error(NULL, "Cannot access static:: when no class scope is active");
+ goto failure;
}
} else {
ce = zend_fetch_class(class_name, flags);
}
- free_alloca(lcname, use_heap);
if (ce) {
- ret_constant = zend_hash_find(&ce->constants_table, constant_name);
- if (ret_constant == NULL) {
+ zend_class_constant *c = zend_hash_find_ptr(&ce->constants_table, constant_name);
+ if (c == NULL) {
if ((flags & ZEND_FETCH_CLASS_SILENT) == 0) {
- zend_throw_error(zend_ce_error, "Undefined class constant '%s::%s'", ZSTR_VAL(class_name), ZSTR_VAL(constant_name));
- zend_string_release(class_name);
- zend_string_free(constant_name);
- return NULL;
+ zend_throw_error(NULL, "Undefined class constant '%s::%s'", ZSTR_VAL(class_name), ZSTR_VAL(constant_name));
+ goto failure;
+ }
+ ret_constant = NULL;
+ } else {
+ if (!zend_verify_const_access(c, scope)) {
+ zend_throw_error(NULL, "Cannot access %s const %s::%s", zend_visibility_string(Z_ACCESS_FLAGS(c->value)), ZSTR_VAL(class_name), ZSTR_VAL(constant_name));
+ goto failure;
}
- } else if (Z_ISREF_P(ret_constant)) {
- ret_constant = Z_REFVAL_P(ret_constant);
+ ret_constant = &c->value;
}
}
- zend_string_release(class_name);
- zend_string_free(constant_name);
+
if (ret_constant && Z_CONSTANT_P(ret_constant)) {
- if (UNEXPECTED(zval_update_constant_ex(ret_constant, 1, ce) != SUCCESS)) {
- return NULL;
+ if (Z_TYPE_P(ret_constant) == IS_CONSTANT_AST) {
+ if (IS_CONSTANT_VISITED(ret_constant)) {
+ zend_throw_error(NULL, "Cannot declare self-referencing constant '%s::%s'", ZSTR_VAL(class_name), ZSTR_VAL(constant_name));
+ goto failure;
+ }
+ MARK_CONSTANT_VISITED(ret_constant);
+ }
+ if (UNEXPECTED(zval_update_constant_ex(ret_constant, ce) != SUCCESS)) {
+ RESET_CONSTANT_VISITED(ret_constant);
+ goto failure;
}
+ RESET_CONSTANT_VISITED(ret_constant);
}
+failure:
+ zend_string_release(class_name);
+ zend_string_free(constant_name);
return ret_constant;
}
@@ -427,7 +436,7 @@ ZEND_API zval *zend_get_constant_ex(zend_string *cname, zend_class_entry *scope,
}
}
-zend_constant *zend_quick_get_constant(const zval *key, zend_ulong flags)
+zend_constant *zend_quick_get_constant(const zval *key, uint32_t flags)
{
zend_constant *c;