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.c219
1 files changed, 85 insertions, 134 deletions
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c
index 4ce3a57458..d08b77a520 100644
--- a/Zend/zend_execute_API.c
+++ b/Zend/zend_execute_API.c
@@ -47,7 +47,7 @@ ZEND_API void (*zend_execute_internal)(zend_execute_data *execute_data, zval *re
/* true globals */
ZEND_API const zend_fcall_info empty_fcall_info = { 0, {{0}, {{0}}, {0}}, NULL, NULL, NULL, 0, 0 };
-ZEND_API const zend_fcall_info_cache empty_fcall_info_cache = { 0, NULL, NULL, NULL, NULL };
+ZEND_API const zend_fcall_info_cache empty_fcall_info_cache = { NULL, NULL, NULL, NULL };
#ifdef ZEND_WIN32
ZEND_TLS HANDLE tq_timer = NULL;
@@ -303,7 +303,7 @@ void shutdown_executor(void) /* {{{ */
zend_hash_graceful_reverse_destroy(&EG(symbol_table));
#if ZEND_DEBUG
- if (GC_G(gc_enabled) && !CG(unclean_shutdown)) {
+ if (gc_enabled() && !CG(unclean_shutdown)) {
gc_collect_cycles();
}
#endif
@@ -336,12 +336,12 @@ void shutdown_executor(void) /* {{{ */
if (c->flags & CONST_PERSISTENT) {
break;
}
- zval_ptr_dtor(&c->value);
+ zval_ptr_dtor_nogc(&c->value);
if (c->name) {
- zend_string_release(c->name);
+ zend_string_release_ex(c->name, 0);
}
efree(c);
- zend_string_release(key);
+ zend_string_release_ex(key, 0);
} ZEND_HASH_FOREACH_END_DEL();
ZEND_HASH_REVERSE_FOREACH_STR_KEY_VAL(EG(function_table), key, zv) {
zend_function *func = Z_PTR_P(zv);
@@ -349,7 +349,7 @@ void shutdown_executor(void) /* {{{ */
break;
}
destroy_op_array(&func->op_array);
- zend_string_release(key);
+ zend_string_release_ex(key, 0);
} ZEND_HASH_FOREACH_END_DEL();
ZEND_HASH_REVERSE_FOREACH_STR_KEY_VAL(EG(class_table), key, zv) {
zend_class_entry *ce = Z_PTR_P(zv);
@@ -357,7 +357,7 @@ void shutdown_executor(void) /* {{{ */
break;
}
destroy_zend_class(zv);
- zend_string_release(key);
+ zend_string_release_ex(key, 0);
} ZEND_HASH_FOREACH_END_DEL();
}
@@ -528,107 +528,64 @@ ZEND_API zend_bool zend_is_executing(void) /* {{{ */
}
/* }}} */
-ZEND_API void _zval_ptr_dtor(zval *zval_ptr ZEND_FILE_LINE_DC) /* {{{ */
+ZEND_API int zend_use_undefined_constant(zend_string *name, zend_ast_attr attr, zval *result) /* {{{ */
{
- i_zval_ptr_dtor(zval_ptr ZEND_FILE_LINE_RELAY_CC);
-}
-/* }}} */
+ char *colon;
-ZEND_API void _zval_internal_ptr_dtor(zval *zval_ptr ZEND_FILE_LINE_DC) /* {{{ */
-{
- if (Z_REFCOUNTED_P(zval_ptr)) {
- Z_DELREF_P(zval_ptr);
- if (Z_REFCOUNT_P(zval_ptr) == 0) {
- _zval_internal_dtor_for_ptr(zval_ptr ZEND_FILE_LINE_CC);
+ if (UNEXPECTED(EG(exception))) {
+ return FAILURE;
+ } else if ((colon = (char*)zend_memrchr(ZSTR_VAL(name), ':', ZSTR_LEN(name)))) {
+ zend_throw_error(NULL, "Undefined class constant '%s'", ZSTR_VAL(name));
+ return FAILURE;
+ } else if ((attr & IS_CONSTANT_UNQUALIFIED) == 0) {
+ zend_throw_error(NULL, "Undefined constant '%s'", ZSTR_VAL(name));
+ return FAILURE;
+ } else {
+ char *actual = ZSTR_VAL(name);
+ size_t actual_len = ZSTR_LEN(name);
+ char *slash = (char *) zend_memrchr(actual, '\\', actual_len);
+
+ if (slash) {
+ actual = slash + 1;
+ actual_len -= (actual - ZSTR_VAL(name));
+ }
+
+ zend_error(E_WARNING, "Use of undefined constant %s - assumed '%s' (this will throw an Error in a future version of PHP)", actual, actual);
+ if (EG(exception)) {
+ return FAILURE;
+ } else {
+ zend_string *result_str = zend_string_init(actual, actual_len, 0);
+ zval_ptr_dtor_nogc(result);
+ ZVAL_NEW_STR(result, result_str);
}
}
+ return SUCCESS;
}
/* }}} */
ZEND_API int zval_update_constant_ex(zval *p, zend_class_entry *scope) /* {{{ */
{
- zval *const_value;
- char *colon;
- zend_bool inline_change;
-
- if (Z_TYPE_P(p) == IS_CONSTANT) {
- if (IS_CONSTANT_VISITED(p)) {
- zend_throw_error(NULL, "Cannot declare self-referencing constant '%s'", Z_STRVAL_P(p));
- return FAILURE;
- }
- inline_change = (Z_TYPE_FLAGS_P(p) & IS_TYPE_REFCOUNTED) != 0;
- SEPARATE_ZVAL_NOREF(p);
- MARK_CONSTANT_VISITED(p);
- if (Z_CONST_FLAGS_P(p) & IS_CONSTANT_CLASS) {
- ZEND_ASSERT(EG(current_execute_data));
- if (inline_change) {
- zend_string_release(Z_STR_P(p));
- }
- if (scope && scope->name) {
- ZVAL_STR_COPY(p, scope->name);
- } else {
- ZVAL_EMPTY_STRING(p);
- }
- } else if (UNEXPECTED((const_value = zend_get_constant_ex(Z_STR_P(p), scope, Z_CONST_FLAGS_P(p))) == NULL)) {
- if (UNEXPECTED(EG(exception))) {
- RESET_CONSTANT_VISITED(p);
- return FAILURE;
- } else if ((colon = (char*)zend_memrchr(Z_STRVAL_P(p), ':', Z_STRLEN_P(p)))) {
- zend_throw_error(NULL, "Undefined class constant '%s'", Z_STRVAL_P(p));
- RESET_CONSTANT_VISITED(p);
- return FAILURE;
- } else {
- if ((Z_CONST_FLAGS_P(p) & IS_CONSTANT_UNQUALIFIED) == 0) {
- zend_throw_error(NULL, "Undefined constant '%s'", Z_STRVAL_P(p));
- RESET_CONSTANT_VISITED(p);
- return FAILURE;
- } else {
- zend_string *save = Z_STR_P(p);
- char *actual = Z_STRVAL_P(p);
- size_t actual_len = Z_STRLEN_P(p);
- char *slash = (char *) zend_memrchr(actual, '\\', actual_len);
- if (slash) {
- actual = slash + 1;
- actual_len -= (actual - Z_STRVAL_P(p));
- }
+ if (Z_TYPE_P(p) == IS_CONSTANT_AST) {
+ zend_ast *ast = Z_ASTVAL_P(p);
- zend_error(E_WARNING, "Use of undefined constant %s - assumed '%s' (this will throw an Error in a future version of PHP)", actual, actual);
- if (EG(exception)) {
- RESET_CONSTANT_VISITED(p);
- return FAILURE;
- }
+ if (ast->kind == ZEND_AST_CONSTANT) {
+ zend_string *name = zend_ast_get_constant_name(ast);
+ zval *zv = zend_get_constant_ex(name, scope, ast->attr);
- if (!inline_change) {
- ZVAL_STRINGL(p, actual, actual_len);
- } else {
- if (slash) {
- ZVAL_STRINGL(p, actual, actual_len);
- zend_string_release(save);
- } else {
- Z_TYPE_INFO_P(p) = Z_REFCOUNTED_P(p) ?
- IS_STRING_EX : IS_INTERNED_STRING_EX;
- }
- }
- }
+ if (UNEXPECTED(zv == NULL)) {
+ return zend_use_undefined_constant(name, ast->attr, p);
}
+ zval_ptr_dtor_nogc(p);
+ ZVAL_COPY_OR_DUP(p, zv);
} else {
- if (inline_change) {
- zend_string_release(Z_STR_P(p));
- }
- ZVAL_COPY_VALUE(p, const_value);
- zval_opt_copy_ctor(p);
- }
- } else if (Z_TYPE_P(p) == IS_CONSTANT_AST) {
- zval tmp;
+ zval tmp;
- inline_change = (Z_TYPE_FLAGS_P(p) & IS_TYPE_REFCOUNTED) != 0;
- if (UNEXPECTED(zend_ast_evaluate(&tmp, Z_ASTVAL_P(p), scope) != SUCCESS)) {
- return FAILURE;
- }
- if (inline_change) {
- zval_ptr_dtor(p);
+ if (UNEXPECTED(zend_ast_evaluate(&tmp, ast, scope) != SUCCESS)) {
+ return FAILURE;
+ }
+ zval_ptr_dtor_nogc(p);
+ ZVAL_COPY_VALUE(p, &tmp);
}
- ZVAL_COPY_VALUE(p, &tmp);
}
return SUCCESS;
}
@@ -673,13 +630,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) /
return FAILURE; /* we would result in an instable executor otherwise */
}
- switch (fci->size) {
- case sizeof(zend_fcall_info):
- break; /* nothing to do currently */
- default:
- zend_error_noreturn(E_CORE_ERROR, "Corrupted fcall_info provided to zend_call_function()");
- break;
- }
+ ZEND_ASSERT(fci->size == sizeof(zend_fcall_info));
/* Initialize execute_data */
if (!EG(current_execute_data)) {
@@ -704,7 +655,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) /
EG(current_execute_data) = &dummy_execute_data;
}
- if (!fci_cache || !fci_cache->initialized) {
+ if (!fci_cache || !fci_cache->function_handler) {
char *error = NULL;
if (!fci_cache) {
@@ -717,7 +668,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) /
= zend_get_callable_name_ex(&fci->function_name, fci->object);
zend_error(E_WARNING, "Invalid callback %s, %s", ZSTR_VAL(callable_name), error);
efree(error);
- zend_string_release(callable_name);
+ zend_string_release_ex(callable_name, 0);
}
if (EG(current_execute_data) == &dummy_execute_data) {
EG(current_execute_data) = dummy_execute_data.prev_execute_data;
@@ -803,8 +754,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) /
if (UNEXPECTED(func->op_array.fn_flags & ZEND_ACC_CLOSURE)) {
uint32_t call_info;
- ZEND_ASSERT(GC_TYPE((zend_object*)func->op_array.prototype) == IS_OBJECT);
- GC_REFCOUNT((zend_object*)func->op_array.prototype)++;
+ GC_ADDREF(ZEND_CLOSURE_OBJECT(func));
call_info = ZEND_CALL_CLOSURE;
if (func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) {
call_info |= ZEND_CALL_FAKE_CLOSURE;
@@ -812,7 +762,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) /
ZEND_ADD_CALL_FLAG(call, call_info);
}
- if (func->type == ZEND_USER_FUNCTION) {
+ if (func->type == ZEND_USER_FUNCTION) {
int call_via_handler = (func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) != 0;
const zend_op *current_opline_before_exception = EG(opline_before_exception);
@@ -821,7 +771,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) /
EG(opline_before_exception) = current_opline_before_exception;
if (call_via_handler) {
/* We must re-initialize function again */
- fci_cache->initialized = 0;
+ fci_cache->function_handler = NULL;
}
} else if (func->type == ZEND_INTERNAL_FUNCTION) {
int call_via_handler = (func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) != 0;
@@ -845,7 +795,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) /
if (call_via_handler) {
/* We must re-initialize function again */
- fci_cache->initialized = 0;
+ fci_cache->function_handler = NULL;
}
} else { /* ZEND_OVERLOADED_FUNCTION */
ZVAL_NULL(fci->retval);
@@ -863,7 +813,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) /
zend_vm_stack_free_args(call);
if (func->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
- zend_string_release(func->common.function_name);
+ zend_string_release_ex(func->common.function_name, 0);
}
efree(func);
@@ -895,7 +845,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) /
ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, const zval *key, int use_autoload) /* {{{ */
{
zend_class_entry *ce = NULL;
- zval args[1];
+ zval args[1], *zv;
zval local_retval;
zend_string *lc_name;
zend_fcall_info fcall_info;
@@ -916,12 +866,12 @@ ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, const zval *k
}
}
- ce = zend_hash_find_ptr(EG(class_table), lc_name);
- if (ce) {
+ zv = zend_hash_find(EG(class_table), lc_name);
+ if (zv) {
if (!key) {
- zend_string_release(lc_name);
+ zend_string_release_ex(lc_name, 0);
}
- return ce;
+ return (zend_class_entry*)Z_PTR_P(zv);
}
/* The compiler is not-reentrant. Make sure we __autoload() only during run-time
@@ -929,18 +879,19 @@ ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, const zval *k
*/
if (!use_autoload || zend_is_compiling()) {
if (!key) {
- zend_string_release(lc_name);
+ zend_string_release_ex(lc_name, 0);
}
return NULL;
}
if (!EG(autoload_func)) {
- zend_function *func = zend_hash_find_ptr(EG(function_table), ZSTR_KNOWN(ZEND_STR_MAGIC_AUTOLOAD));
+ zend_function *func = zend_fetch_function(ZSTR_KNOWN(ZEND_STR_MAGIC_AUTOLOAD));
+
if (func) {
EG(autoload_func) = func;
} else {
if (!key) {
- zend_string_release(lc_name);
+ zend_string_release_ex(lc_name, 0);
}
return NULL;
}
@@ -949,7 +900,7 @@ ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, const zval *k
/* Verify class name before passing it to __autoload() */
if (!key && strspn(ZSTR_VAL(name), "0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377\\") != ZSTR_LEN(name)) {
- zend_string_release(lc_name);
+ zend_string_release_ex(lc_name, 0);
return NULL;
}
@@ -960,7 +911,7 @@ ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, const zval *k
if (zend_hash_add_empty_element(EG(in_autoload), lc_name) == NULL) {
if (!key) {
- zend_string_release(lc_name);
+ zend_string_release_ex(lc_name, 0);
}
return NULL;
}
@@ -981,9 +932,7 @@ ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, const zval *k
fcall_info.object = NULL;
fcall_info.no_separation = 1;
- fcall_cache.initialized = 1;
fcall_cache.function_handler = EG(autoload_func);
- fcall_cache.calling_scope = NULL;
fcall_cache.called_scope = NULL;
fcall_cache.object = NULL;
@@ -994,14 +943,14 @@ ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, const zval *k
zend_exception_restore();
zval_ptr_dtor(&args[0]);
- zval_dtor(&fcall_info.function_name);
+ zval_ptr_dtor_str(&fcall_info.function_name);
zend_hash_del(EG(in_autoload), lc_name);
zval_ptr_dtor(&local_retval);
if (!key) {
- zend_string_release(lc_name);
+ zend_string_release_ex(lc_name, 0);
}
return ce;
}
@@ -1055,7 +1004,7 @@ ZEND_API int zend_eval_stringl(char *str, size_t str_len, zval *retval_ptr, char
int retval;
if (retval_ptr) {
- ZVAL_NEW_STR(&pv, zend_string_alloc(str_len + sizeof("return ;")-1, 1));
+ ZVAL_NEW_STR(&pv, zend_string_alloc(str_len + sizeof("return ;")-1, 0));
memcpy(Z_STRVAL(pv), "return ", sizeof("return ") - 1);
memcpy(Z_STRVAL(pv) + sizeof("return ") - 1, str, str_len);
Z_STRVAL(pv)[Z_STRLEN(pv) - 1] = ';';
@@ -1106,7 +1055,7 @@ ZEND_API int zend_eval_stringl(char *str, size_t str_len, zval *retval_ptr, char
} else {
retval = FAILURE;
}
- zval_dtor(&pv);
+ zval_ptr_dtor_str(&pv);
return retval;
}
/* }}} */
@@ -1530,12 +1479,11 @@ ZEND_API zend_array *zend_rebuild_symbol_table(void) /* {{{ */
}
zend_hash_extend(symbol_table, ex->func->op_array.last_var, 0);
} else {
- symbol_table = ex->symbol_table = emalloc(sizeof(zend_array));
- zend_hash_init(symbol_table, ex->func->op_array.last_var, NULL, ZVAL_PTR_DTOR, 0);
+ symbol_table = ex->symbol_table = zend_new_array(ex->func->op_array.last_var);
if (!ex->func->op_array.last_var) {
return symbol_table;
}
- zend_hash_real_init(symbol_table, 0);
+ zend_hash_real_init_mixed(symbol_table);
/*printf("Cache miss! Initialized %x\n", EG(active_symbol_table));*/
}
if (EXPECTED(ex->func->op_array.last_var)) {
@@ -1566,7 +1514,7 @@ ZEND_API void zend_attach_symbol_table(zend_execute_data *execute_data) /* {{{ *
zval *var = EX_VAR_NUM(0);
do {
- zval *zv = zend_hash_find(ht, *str);
+ zval *zv = zend_hash_find_ex(ht, *str, 1);
if (zv) {
if (Z_TYPE_P(zv) == IS_INDIRECT) {
@@ -1632,8 +1580,7 @@ ZEND_API int zend_set_local_var(zend_string *name, zval *value, int force) /* {{
do {
if (ZSTR_H(*str) == h &&
- ZSTR_LEN(*str) == ZSTR_LEN(name) &&
- memcmp(ZSTR_VAL(*str), ZSTR_VAL(name), ZSTR_LEN(name)) == 0) {
+ zend_string_equal_content(*str, name)) {
zval *var = EX_VAR_NUM(str - op_array->vars);
ZVAL_COPY_VALUE(var, value);
return SUCCESS;
@@ -1644,11 +1591,13 @@ ZEND_API int zend_set_local_var(zend_string *name, zval *value, int force) /* {{
if (force) {
zend_array *symbol_table = zend_rebuild_symbol_table();
if (symbol_table) {
- return zend_hash_update(symbol_table, name, value) ? SUCCESS : FAILURE;
+ zend_hash_update(symbol_table, name, value);
+ return SUCCESS;
}
}
} else {
- return (zend_hash_update_ind(execute_data->symbol_table, name, value) != NULL) ? SUCCESS : FAILURE;
+ zend_hash_update_ind(execute_data->symbol_table, name, value);
+ return SUCCESS;
}
}
return FAILURE;
@@ -1686,11 +1635,13 @@ ZEND_API int zend_set_local_var_str(const char *name, size_t len, zval *value, i
if (force) {
zend_array *symbol_table = zend_rebuild_symbol_table();
if (symbol_table) {
- return zend_hash_str_update(symbol_table, name, len, value) ? SUCCESS : FAILURE;
+ zend_hash_str_update(symbol_table, name, len, value);
+ return SUCCESS;
}
}
} else {
- return (zend_hash_str_update_ind(execute_data->symbol_table, name, len, value) != NULL) ? SUCCESS : FAILURE;
+ zend_hash_str_update_ind(execute_data->symbol_table, name, len, value);
+ return SUCCESS;
}
}
return FAILURE;