summaryrefslogtreecommitdiff
path: root/Zend/zend_builtin_functions.c
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2014-12-21 03:03:49 +0000
committerAndrea Faulds <ajf@ajf.me>2014-12-21 03:03:49 +0000
commit0833fd4619978c0522056b44dd53cd3b9d974cdd (patch)
tree19ad1d216fc70e025d5609ba58ef74e4ed8a1b30 /Zend/zend_builtin_functions.c
parentc94f62d0d98f4373bbf8f68c234b16d52c5f3273 (diff)
downloadphp-git-0833fd4619978c0522056b44dd53cd3b9d974cdd.tar.gz
Allow arrays with define(), to match const syntax support
Diffstat (limited to 'Zend/zend_builtin_functions.c')
-rw-r--r--Zend/zend_builtin_functions.c78
1 files changed, 77 insertions, 1 deletions
diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c
index c05e797013..f956f492b4 100644
--- a/Zend/zend_builtin_functions.c
+++ b/Zend/zend_builtin_functions.c
@@ -688,6 +688,71 @@ ZEND_FUNCTION(error_reporting)
}
/* }}} */
+static int validate_constant_array(HashTable *ht) /* {{{ */
+{
+ int ret = 1;
+ zval *val;
+
+ ht->u.v.nApplyCount++;
+ ZEND_HASH_FOREACH_VAL_IND(ht, val) {
+ ZVAL_DEREF(val);
+ if (Z_REFCOUNTED_P(val)) {
+ if (Z_TYPE_P(val) == IS_ARRAY) {
+ if (!Z_IMMUTABLE_P(val)) {
+ if (Z_ARRVAL_P(val)->u.v.nApplyCount > 0) {
+ zend_error(E_WARNING, "Constants cannot be recursive arrays");
+ ret = 0;
+ break;
+ } else if (!validate_constant_array(Z_ARRVAL_P(val))) {
+ ret = 0;
+ break;
+ }
+ }
+ } else if (Z_TYPE_P(val) != IS_STRING && Z_TYPE_P(val) != IS_RESOURCE) {
+ zend_error(E_WARNING, "Constants may only evaluate to scalar values or arrays");
+ ret = 0;
+ break;
+ }
+ }
+ } ZEND_HASH_FOREACH_END();
+ ht->u.v.nApplyCount--;
+ return ret;
+}
+/* }}} */
+
+static void copy_constant_array(zval *dst, zval *src) /* {{{ */
+{
+ zend_string *key;
+ zend_ulong idx;
+ zval *new_val, *val;
+
+ array_init_size(dst, zend_hash_num_elements(Z_ARRVAL_P(src)));
+ ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(src), idx, key, val) {
+ /* constant arrays can't contain references */
+ if (Z_ISREF_P(val)) {
+ if (Z_REFCOUNT_P(val) == 1) {
+ ZVAL_UNREF(val);
+ } else {
+ Z_DELREF_P(val);
+ val = Z_REFVAL_P(val);
+ }
+ }
+ if (key) {
+ new_val = zend_hash_add_new(Z_ARRVAL_P(dst), key, val);
+ } else {
+ new_val = zend_hash_index_add_new(Z_ARRVAL_P(dst), idx, val);
+ }
+ if (Z_TYPE_P(val) == IS_ARRAY) {
+ if (!Z_IMMUTABLE_P(val)) {
+ copy_constant_array(new_val, val);
+ }
+ } else if (Z_REFCOUNTED_P(val)) {
+ Z_ADDREF_P(val);
+ }
+ } ZEND_HASH_FOREACH_END();
+}
+/* }}} */
+
/* {{{ proto bool define(string constant_name, mixed value, boolean case_insensitive=false)
Define a new constant */
ZEND_FUNCTION(define)
@@ -733,6 +798,16 @@ repeat:
case IS_RESOURCE:
case IS_NULL:
break;
+ case IS_ARRAY:
+ if (!Z_IMMUTABLE_P(val)) {
+ if (!validate_constant_array(Z_ARRVAL_P(val))) {
+ RETURN_FALSE;
+ } else {
+ copy_constant_array(&c.value, val);
+ goto register_constant;
+ }
+ }
+ break;
case IS_OBJECT:
if (Z_TYPE(val_free) == IS_UNDEF) {
if (Z_OBJ_HT_P(val)->get) {
@@ -749,13 +824,14 @@ repeat:
}
/* no break */
default:
- zend_error(E_WARNING,"Constants may only evaluate to scalar values");
+ zend_error(E_WARNING, "Constants may only evaluate to scalar values or arrays");
zval_ptr_dtor(&val_free);
RETURN_FALSE;
}
ZVAL_DUP(&c.value, val);
zval_ptr_dtor(&val_free);
+register_constant:
c.flags = case_sensitive; /* non persistent */
c.name = zend_string_copy(name);
c.module_number = PHP_USER_CONSTANT;