summaryrefslogtreecommitdiff
path: root/Zend/zend_execute_API.c
diff options
context:
space:
mode:
Diffstat (limited to 'Zend/zend_execute_API.c')
-rw-r--r--Zend/zend_execute_API.c334
1 files changed, 177 insertions, 157 deletions
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c
index 779e6d886f..eabebacce4 100644
--- a/Zend/zend_execute_API.c
+++ b/Zend/zend_execute_API.c
@@ -478,188 +478,208 @@ ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *sco
if (IS_CONSTANT_VISITED(p)) {
zend_error(E_ERROR, "Cannot declare self-referencing constant '%s'", Z_STRVAL_P(p));
- } else if ((Z_TYPE_P(p) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
- int refcount;
- zend_uchar is_ref;
+ return FAILURE;
+ }
+ switch (Z_TYPE_P(p) & IS_CONSTANT_TYPE_MASK) {
+ case IS_CONSTANT: {
+ int refcount;
+ zend_uchar is_ref;
- SEPARATE_ZVAL_IF_NOT_REF(pp);
- p = *pp;
+ SEPARATE_ZVAL_IF_NOT_REF(pp);
+ p = *pp;
- MARK_CONSTANT_VISITED(p);
+ MARK_CONSTANT_VISITED(p);
- refcount = Z_REFCOUNT_P(p);
- is_ref = Z_ISREF_P(p);
+ refcount = Z_REFCOUNT_P(p);
+ is_ref = Z_ISREF_P(p);
- if (!zend_get_constant_ex(p->value.str.val, p->value.str.len, &const_value, scope, Z_REAL_TYPE_P(p) TSRMLS_CC)) {
- char *actual = Z_STRVAL_P(p);
+ if (!zend_get_constant_ex(p->value.str.val, p->value.str.len, &const_value, scope, Z_REAL_TYPE_P(p) TSRMLS_CC)) {
+ char *actual = Z_STRVAL_P(p);
- if ((colon = (char*)zend_memrchr(Z_STRVAL_P(p), ':', Z_STRLEN_P(p)))) {
- zend_error(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(p));
- Z_STRLEN_P(p) -= ((colon - Z_STRVAL_P(p)) + 1);
- if (inline_change) {
- colon = estrndup(colon, Z_STRLEN_P(p));
- str_efree(Z_STRVAL_P(p));
- Z_STRVAL_P(p) = colon;
- } else {
- Z_STRVAL_P(p) = colon + 1;
- }
- } else {
- char *save = actual, *slash;
- int actual_len = Z_STRLEN_P(p);
- if ((Z_TYPE_P(p) & IS_CONSTANT_UNQUALIFIED) && (slash = (char *)zend_memrchr(actual, '\\', actual_len))) {
- actual = slash + 1;
- actual_len -= (actual - Z_STRVAL_P(p));
+ if ((colon = (char*)zend_memrchr(Z_STRVAL_P(p), ':', Z_STRLEN_P(p)))) {
+ zend_error(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(p));
+ Z_STRLEN_P(p) -= ((colon - Z_STRVAL_P(p)) + 1);
if (inline_change) {
- actual = estrndup(actual, actual_len);
- Z_STRVAL_P(p) = actual;
- Z_STRLEN_P(p) = actual_len;
- }
- }
- if (actual[0] == '\\') {
- if (inline_change) {
- memmove(Z_STRVAL_P(p), Z_STRVAL_P(p)+1, Z_STRLEN_P(p));
- --Z_STRLEN_P(p);
+ colon = estrndup(colon, Z_STRLEN_P(p));
+ str_efree(Z_STRVAL_P(p));
+ Z_STRVAL_P(p) = colon;
} else {
- ++actual;
+ Z_STRVAL_P(p) = colon + 1;
}
- --actual_len;
- }
- if ((Z_TYPE_P(p) & IS_CONSTANT_UNQUALIFIED) == 0) {
- int fix_save = 0;
- if (save[0] == '\\') {
- save++;
- fix_save = 1;
+ } else {
+ char *save = actual, *slash;
+ int actual_len = Z_STRLEN_P(p);
+ if ((Z_TYPE_P(p) & IS_CONSTANT_UNQUALIFIED) && (slash = (char *)zend_memrchr(actual, '\\', actual_len))) {
+ actual = slash + 1;
+ actual_len -= (actual - Z_STRVAL_P(p));
+ if (inline_change) {
+ actual = estrndup(actual, actual_len);
+ Z_STRVAL_P(p) = actual;
+ Z_STRLEN_P(p) = actual_len;
+ }
}
- zend_error(E_ERROR, "Undefined constant '%s'", save);
- if (fix_save) {
- save--;
+ if (actual[0] == '\\') {
+ if (inline_change) {
+ memmove(Z_STRVAL_P(p), Z_STRVAL_P(p)+1, Z_STRLEN_P(p));
+ --Z_STRLEN_P(p);
+ } else {
+ ++actual;
+ }
+ --actual_len;
}
- if (inline_change) {
+ if ((Z_TYPE_P(p) & IS_CONSTANT_UNQUALIFIED) == 0) {
+ int fix_save = 0;
+ if (save[0] == '\\') {
+ save++;
+ fix_save = 1;
+ }
+ zend_error(E_ERROR, "Undefined constant '%s'", save);
+ if (fix_save) {
+ save--;
+ }
+ if (inline_change) {
+ str_efree(save);
+ }
+ save = NULL;
+ }
+ if (inline_change && save && save != actual) {
str_efree(save);
}
- save = NULL;
- }
- if (inline_change && save && save != actual) {
- str_efree(save);
+ zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", actual, actual);
+ p->type = IS_STRING;
+ if (!inline_change) {
+ Z_STRVAL_P(p) = actual;
+ Z_STRLEN_P(p) = actual_len;
+ zval_copy_ctor(p);
+ }
}
- zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", actual, actual);
- p->type = IS_STRING;
- if (!inline_change) {
- Z_STRVAL_P(p) = actual;
- Z_STRLEN_P(p) = actual_len;
- zval_copy_ctor(p);
+ } else {
+ if (inline_change) {
+ str_efree(Z_STRVAL_P(p));
}
+ *p = const_value;
}
- } else {
- if (inline_change) {
- str_efree(Z_STRVAL_P(p));
- }
- *p = const_value;
- }
- Z_SET_REFCOUNT_P(p, refcount);
- Z_SET_ISREF_TO_P(p, is_ref);
- } else if (Z_TYPE_P(p) == IS_CONSTANT_ARRAY) {
- zval **element, *new_val;
- char *str_index;
- uint str_index_len;
- ulong num_index;
- int ret;
-
- SEPARATE_ZVAL_IF_NOT_REF(pp);
- p = *pp;
- Z_TYPE_P(p) = IS_ARRAY;
-
- if (!inline_change) {
- zval *tmp;
- HashTable *tmp_ht = NULL;
-
- ALLOC_HASHTABLE(tmp_ht);
- zend_hash_init(tmp_ht, zend_hash_num_elements(Z_ARRVAL_P(p)), NULL, ZVAL_PTR_DTOR, 0);
- zend_hash_copy(tmp_ht, Z_ARRVAL_P(p), (copy_ctor_func_t) zval_deep_copy, (void *) &tmp, sizeof(zval *));
- Z_ARRVAL_P(p) = tmp_ht;
+ Z_SET_REFCOUNT_P(p, refcount);
+ Z_SET_ISREF_TO_P(p, is_ref);
}
-
- /* First go over the array and see if there are any constant indices */
- zend_hash_internal_pointer_reset(Z_ARRVAL_P(p));
- while (zend_hash_get_current_data(Z_ARRVAL_P(p), (void **) &element) == SUCCESS) {
- if (!(Z_TYPE_PP(element) & IS_CONSTANT_INDEX)) {
- zend_hash_move_forward(Z_ARRVAL_P(p));
- continue;
+ break;
+
+ case IS_CONSTANT_ARRAY: {
+ zval **element, *new_val;
+ char *str_index;
+ uint str_index_len;
+ ulong num_index;
+ int ret;
+
+ SEPARATE_ZVAL_IF_NOT_REF(pp);
+ p = *pp;
+ Z_TYPE_P(p) = IS_ARRAY;
+
+ if (!inline_change) {
+ zval *tmp;
+ HashTable *tmp_ht = NULL;
+
+ ALLOC_HASHTABLE(tmp_ht);
+ zend_hash_init(tmp_ht, zend_hash_num_elements(Z_ARRVAL_P(p)), NULL, ZVAL_PTR_DTOR, 0);
+ zend_hash_copy(tmp_ht, Z_ARRVAL_P(p), (copy_ctor_func_t) zval_deep_copy, (void *) &tmp, sizeof(zval *));
+ Z_ARRVAL_P(p) = tmp_ht;
}
- Z_TYPE_PP(element) &= ~IS_CONSTANT_INDEX;
- if (zend_hash_get_current_key_ex(Z_ARRVAL_P(p), &str_index, &str_index_len, &num_index, 0, NULL) != HASH_KEY_IS_STRING) {
- zend_hash_move_forward(Z_ARRVAL_P(p));
- continue;
- }
- if (!zend_get_constant_ex(str_index, str_index_len - 3, &const_value, scope, str_index[str_index_len - 2] TSRMLS_CC)) {
- char *actual;
- const char *save = str_index;
- if ((colon = (char*)zend_memrchr(str_index, ':', str_index_len - 3))) {
- zend_error(E_ERROR, "Undefined class constant '%s'", str_index);
- str_index_len -= ((colon - str_index) + 1);
- str_index = colon;
- } else {
- if (str_index[str_index_len - 2] & IS_CONSTANT_UNQUALIFIED) {
- if ((actual = (char *)zend_memrchr(str_index, '\\', str_index_len - 3))) {
- actual++;
- str_index_len -= (actual - str_index);
- str_index = actual;
+
+ /* First go over the array and see if there are any constant indices */
+ zend_hash_internal_pointer_reset(Z_ARRVAL_P(p));
+ while (zend_hash_get_current_data(Z_ARRVAL_P(p), (void **) &element) == SUCCESS) {
+ if (!(Z_TYPE_PP(element) & IS_CONSTANT_INDEX)) {
+ zend_hash_move_forward(Z_ARRVAL_P(p));
+ continue;
+ }
+ Z_TYPE_PP(element) &= ~IS_CONSTANT_INDEX;
+ if (zend_hash_get_current_key_ex(Z_ARRVAL_P(p), &str_index, &str_index_len, &num_index, 0, NULL) != HASH_KEY_IS_STRING) {
+ zend_hash_move_forward(Z_ARRVAL_P(p));
+ continue;
+ }
+ if (str_index[str_index_len - 2] == IS_CONSTANT_AST) {
+ zend_ast_evaluate(&const_value, *(zend_ast **)str_index);
+ ZEND_AST_DEL_REF(*(zend_ast **)str_index);
+ } else if (!zend_get_constant_ex(str_index, str_index_len - 3, &const_value, scope, str_index[str_index_len - 2] TSRMLS_CC)) {
+ char *actual;
+ const char *save = str_index;
+ if ((colon = (char*)zend_memrchr(str_index, ':', str_index_len - 3))) {
+ zend_error(E_ERROR, "Undefined class constant '%s'", str_index);
+ str_index_len -= ((colon - str_index) + 1);
+ str_index = colon;
+ } else {
+ if (str_index[str_index_len - 2] & IS_CONSTANT_UNQUALIFIED) {
+ if ((actual = (char *)zend_memrchr(str_index, '\\', str_index_len - 3))) {
+ actual++;
+ str_index_len -= (actual - str_index);
+ str_index = actual;
+ }
}
+ if (str_index[0] == '\\') {
+ ++str_index;
+ --str_index_len;
+ }
+ if (save[0] == '\\') {
+ ++save;
+ }
+ if ((str_index[str_index_len - 2] & IS_CONSTANT_UNQUALIFIED) == 0) {
+ zend_error(E_ERROR, "Undefined constant '%s'", save);
+ }
+ zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", str_index, str_index);
}
- if (str_index[0] == '\\') {
- ++str_index;
- --str_index_len;
- }
- if (save[0] == '\\') {
- ++save;
- }
- if ((str_index[str_index_len - 2] & IS_CONSTANT_UNQUALIFIED) == 0) {
- zend_error(E_ERROR, "Undefined constant '%s'", save);
- }
- zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", str_index, str_index);
+ ZVAL_STRINGL(&const_value, str_index, str_index_len-3, 1);
}
- ZVAL_STRINGL(&const_value, str_index, str_index_len-3, 1);
- }
- if (Z_REFCOUNT_PP(element) > 1) {
- ALLOC_ZVAL(new_val);
- *new_val = **element;
- zval_copy_ctor(new_val);
- Z_SET_REFCOUNT_P(new_val, 1);
- Z_UNSET_ISREF_P(new_val);
-
- /* preserve this bit for inheritance */
- Z_TYPE_PP(element) |= IS_CONSTANT_INDEX;
- zval_ptr_dtor(element);
- *element = new_val;
- }
+ if (Z_REFCOUNT_PP(element) > 1) {
+ ALLOC_ZVAL(new_val);
+ *new_val = **element;
+ zval_copy_ctor(new_val);
+ Z_SET_REFCOUNT_P(new_val, 1);
+ Z_UNSET_ISREF_P(new_val);
+
+ /* preserve this bit for inheritance */
+ Z_TYPE_PP(element) |= IS_CONSTANT_INDEX;
+ zval_ptr_dtor(element);
+ *element = new_val;
+ }
- switch (Z_TYPE(const_value)) {
- case IS_STRING:
- ret = zend_symtable_update_current_key(Z_ARRVAL_P(p), Z_STRVAL(const_value), Z_STRLEN(const_value) + 1, HASH_UPDATE_KEY_IF_BEFORE);
- break;
- case IS_BOOL:
- case IS_LONG:
- ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL, 0, Z_LVAL(const_value), HASH_UPDATE_KEY_IF_BEFORE, NULL);
- break;
- case IS_DOUBLE:
- ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL, 0, zend_dval_to_lval(Z_DVAL(const_value)), HASH_UPDATE_KEY_IF_BEFORE, NULL);
- break;
- case IS_NULL:
- ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_STRING, "", 1, 0, HASH_UPDATE_KEY_IF_BEFORE, NULL);
- break;
- default:
- ret = SUCCESS;
- break;
- }
- if (ret == SUCCESS) {
- zend_hash_move_forward(Z_ARRVAL_P(p));
+ switch (Z_TYPE(const_value)) {
+ case IS_STRING:
+ ret = zend_symtable_update_current_key(Z_ARRVAL_P(p), Z_STRVAL(const_value), Z_STRLEN(const_value) + 1, HASH_UPDATE_KEY_IF_BEFORE);
+ break;
+ case IS_BOOL:
+ case IS_LONG:
+ ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL, 0, Z_LVAL(const_value), HASH_UPDATE_KEY_IF_BEFORE, NULL);
+ break;
+ case IS_DOUBLE:
+ ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL, 0, zend_dval_to_lval(Z_DVAL(const_value)), HASH_UPDATE_KEY_IF_BEFORE, NULL);
+ break;
+ case IS_NULL:
+ ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_STRING, "", 1, 0, HASH_UPDATE_KEY_IF_BEFORE, NULL);
+ break;
+ default:
+ ret = SUCCESS;
+ break;
+ }
+ if (ret == SUCCESS) {
+ zend_hash_move_forward(Z_ARRVAL_P(p));
+ }
+ zval_dtor(&const_value);
}
- 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));
+ }
+ break;
+
+ case IS_CONSTANT_AST: {
+ zend_ast *ast = Z_AST_P(p);
+
+ MARK_CONSTANT_VISITED(p);
+
+ zend_ast_evaluate(p, ast TSRMLS_CC);
+ ZEND_AST_DEL_REF(ast);
}
- 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));
}
return 0;
}