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.c237
1 files changed, 108 insertions, 129 deletions
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c
index f356b8d910..96aa0bad23 100644
--- a/Zend/zend_execute_API.c
+++ b/Zend/zend_execute_API.c
@@ -146,7 +146,6 @@ void init_executor(TSRMLS_D) /* {{{ */
EG(in_execution) = 0;
EG(in_autoload) = NULL;
EG(autoload_func) = NULL;
- EG(error_handling) = EH_NORMAL;
zend_vm_stack_init(TSRMLS_C);
zend_vm_stack_push((void *) NULL TSRMLS_CC);
@@ -504,64 +503,29 @@ ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *sco
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 ((colon = zend_memrchr(Z_STRVAL_P(p), ':', Z_STRLEN_P(p)))) {
- zend_error(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(p));
+ if ((colon = zend_memrchr(Z_STRVAL_P(p), ':', Z_STRLEN_P(p))) &&
+ colon > Z_STRVAL_P(p) &&
+ *(colon-1) == ':') {
+ if ((Z_TYPE_P(p) & IS_CONSTANT_RT_NS_CHECK) == 0) {
+ zend_error(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(p));
+ } else if (Z_TYPE_P(p) & ZEND_FETCH_CLASS_RT_NS_CHECK) {
+ zend_error(E_ERROR, "Undefined 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));
+ colon = estrndup(colon + 1, Z_STRLEN_P(p));
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 (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);
- } else {
- ++actual;
- }
- --actual_len;
- }
- 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) {
- efree(save);
- }
- save = NULL;
- }
- if (inline_change && save && save != actual) {
- 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);
- }
+ } else if (Z_TYPE_P(p) & ZEND_FETCH_CLASS_RT_NS_CHECK) {
+ zend_error(E_ERROR, "Undefined constant '%s'", Z_STRVAL_P(p));
+ }
+ zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", Z_STRVAL_P(p), Z_STRVAL_P(p));
+ p->type = IS_STRING;
+ if (!inline_change) {
+ zval_copy_ctor(p);
}
} else {
if (inline_change) {
@@ -606,29 +570,20 @@ ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *sco
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, *save = str_index;
- if ((colon = 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) {
- actual = (char *)zend_memrchr(str_index, '\\', str_index_len - 3) + 1;
- str_index_len -= (actual - str_index);
- str_index = actual;
- }
- if (str_index[0] == '\\') {
- ++str_index;
- --str_index_len;
+ if ((colon = zend_memrchr(str_index, ':', str_index_len - 3)) &&
+ colon > str_index &&
+ *(colon-1) == ':') {
+ if ((str_index[str_index_len - 2] & IS_CONSTANT_RT_NS_CHECK) == 0) {
+ zend_error(E_ERROR, "Undefined class constant '%s'", str_index);
+ } else if (str_index[str_index_len - 2] & ZEND_FETCH_CLASS_RT_NS_CHECK) {
+ zend_error(E_ERROR, "Undefined constant '%s'", str_index);
}
- 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);
- }
+ str_index_len -= ((colon - str_index) + 1);
+ str_index = colon + 1;
+ } else if (str_index[str_index_len - 2] & ZEND_FETCH_CLASS_RT_NS_CHECK) {
+ zend_error(E_ERROR, "Undefined constant '%s'", str_index);
+ }
+ 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);
}
@@ -715,7 +670,7 @@ int call_user_function_ex(HashTable *function_table, zval **object_pp, zval *fun
fci.size = sizeof(fci);
fci.function_table = function_table;
- fci.object_ptr = object_pp ? *object_pp : NULL;
+ fci.object_pp = object_pp;
fci.function_name = function_name;
fci.retval_ptr_ptr = retval_ptr_ptr;
fci.param_count = param_count;
@@ -782,7 +737,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
fci_cache = &fci_cache_local;
}
- if (!zend_is_callable_ex(fci->function_name, fci->object_ptr, IS_CALLABLE_CHECK_SILENT, &callable_name, NULL, fci_cache, &error TSRMLS_CC)) {
+ if (!zend_is_callable_ex(fci->function_name, fci->object_pp, IS_CALLABLE_CHECK_SILENT, &callable_name, NULL, fci_cache, &error TSRMLS_CC)) {
if (error) {
zend_error(E_WARNING, "Invalid callback %s, %s", callable_name, error);
efree(error);
@@ -805,10 +760,10 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
EX(function_state).function = fci_cache->function_handler;
calling_scope = fci_cache->calling_scope;
called_scope = fci_cache->called_scope;
- fci->object_ptr = fci_cache->object_ptr;
- EX(object) = fci->object_ptr;
- if (fci->object_ptr && Z_TYPE_P(fci->object_ptr) == IS_OBJECT &&
- (!EG(objects_store).object_buckets || !EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(fci->object_ptr)].valid)) {
+ fci->object_pp = fci_cache->object_pp;
+ EX(object) = fci->object_pp ? *fci->object_pp : NULL;
+ if (fci->object_pp && *fci->object_pp && Z_TYPE_PP(fci->object_pp) == IS_OBJECT &&
+ (!EG(objects_store).object_buckets || !EG(objects_store).object_buckets[Z_OBJ_HANDLE_PP(fci->object_pp)].valid)) {
return FAILURE;
}
@@ -886,11 +841,11 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
EG(called_scope) = NULL;
}
- if (fci->object_ptr) {
+ if (fci->object_pp) {
if ((EX(function_state).function->common.fn_flags & ZEND_ACC_STATIC)) {
EG(This) = NULL;
} else {
- EG(This) = fci->object_ptr;
+ EG(This) = *fci->object_pp;
if (!PZVAL_IS_REF(EG(This))) {
Z_ADDREF_P(EG(This)); /* For $this pointer */
@@ -943,11 +898,14 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
EG(opline_ptr) = original_opline_ptr;
} else if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION) {
int call_via_handler = (EX(function_state).function->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0;
+ zend_error_handling error_handling;
+ zend_save_error_handling(&error_handling TSRMLS_CC);
ALLOC_INIT_ZVAL(*fci->retval_ptr_ptr);
if (EX(function_state).function->common.scope) {
EG(scope) = EX(function_state).function->common.scope;
}
- ((zend_internal_function *) EX(function_state).function)->handler(fci->param_count, *fci->retval_ptr_ptr, fci->retval_ptr_ptr, fci->object_ptr, 1 TSRMLS_CC);
+ ((zend_internal_function *) EX(function_state).function)->handler(fci->param_count, *fci->retval_ptr_ptr, fci->retval_ptr_ptr, (fci->object_pp?*fci->object_pp:NULL), 1 TSRMLS_CC);
+ zend_restore_error_handling(&error_handling TSRMLS_CC);
/* We shouldn't fix bad extensions here,
because it can break proper ones (Bug #34045)
if (!EX(function_state).function->common.return_reference)
@@ -967,8 +925,11 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
ALLOC_INIT_ZVAL(*fci->retval_ptr_ptr);
/* Not sure what should be done here if it's a static method */
- if (fci->object_ptr) {
- Z_OBJ_HT_P(fci->object_ptr)->call_method(EX(function_state).function->common.function_name, fci->param_count, *fci->retval_ptr_ptr, fci->retval_ptr_ptr, fci->object_ptr, 1 TSRMLS_CC);
+ if (fci->object_pp) {
+ zend_error_handling error_handling;
+ zend_save_error_handling(&error_handling TSRMLS_CC);
+ Z_OBJ_HT_PP(fci->object_pp)->call_method(EX(function_state).function->common.function_name, fci->param_count, *fci->retval_ptr_ptr, fci->retval_ptr_ptr, *fci->object_pp, 1 TSRMLS_CC);
+ zend_restore_error_handling(&error_handling TSRMLS_CC);
} else {
zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object");
}
@@ -1006,9 +967,10 @@ ZEND_API int zend_lookup_class_ex(const char *name, int name_length, int use_aut
zval autoload_function;
zval *class_name_ptr;
zval *retval_ptr = NULL;
- int retval, lc_length;
+ int retval;
char *lc_name;
char *lc_free;
+ zval *exception;
zend_fcall_info fcall_info;
zend_fcall_info_cache fcall_cache;
char dummy = 1;
@@ -1020,14 +982,13 @@ ZEND_API int zend_lookup_class_ex(const char *name, int name_length, int use_aut
lc_free = lc_name = do_alloca(name_length + 1, use_heap);
zend_str_tolower_copy(lc_name, name, name_length);
- lc_length = name_length + 1;
- if (lc_name[0] == '\\') {
- lc_name += 1;
- lc_length -= 1;
+ if (lc_name[0] == ':' && lc_name[1] == ':') {
+ lc_name += 2;
+ name_length -= 2;
}
- if (zend_hash_find(EG(class_table), lc_name, lc_length, (void **) ce) == SUCCESS) {
+ if (zend_hash_find(EG(class_table), lc_name, name_length + 1, (void **) ce) == SUCCESS) {
free_alloca(lc_free, use_heap);
return SUCCESS;
}
@@ -1045,7 +1006,7 @@ ZEND_API int zend_lookup_class_ex(const char *name, int name_length, int use_aut
zend_hash_init(EG(in_autoload), 0, NULL, NULL, 0);
}
- if (zend_hash_add(EG(in_autoload), lc_name, lc_length, (void**)&dummy, sizeof(char), NULL) == FAILURE) {
+ if (zend_hash_add(EG(in_autoload), lc_name, name_length + 1, (void**)&dummy, sizeof(char), NULL) == FAILURE) {
free_alloca(lc_free, use_heap);
return FAILURE;
}
@@ -1065,35 +1026,42 @@ ZEND_API int zend_lookup_class_ex(const char *name, int name_length, int use_aut
fcall_info.retval_ptr_ptr = &retval_ptr;
fcall_info.param_count = 1;
fcall_info.params = args;
- fcall_info.object_ptr = NULL;
+ fcall_info.object_pp = NULL;
fcall_info.no_separation = 1;
fcall_cache.initialized = EG(autoload_func) ? 1 : 0;
fcall_cache.function_handler = EG(autoload_func);
fcall_cache.calling_scope = NULL;
fcall_cache.called_scope = NULL;
- fcall_cache.object_ptr = NULL;
+ fcall_cache.object_pp = NULL;
+ exception = EG(exception);
zend_exception_save(TSRMLS_C);
retval = zend_call_function(&fcall_info, &fcall_cache TSRMLS_CC);
- zend_exception_restore(TSRMLS_C);
-
EG(autoload_func) = fcall_cache.function_handler;
zval_ptr_dtor(&class_name_ptr);
- zend_hash_del(EG(in_autoload), lc_name, lc_length);
+ zend_hash_del(EG(in_autoload), lc_name, name_length + 1);
- if (retval_ptr) {
- zval_ptr_dtor(&retval_ptr);
+ if (retval == FAILURE) {
+ zend_exception_restore(TSRMLS_C);
+ free_alloca(lc_free, use_heap);
+ return FAILURE;
}
- if (retval == FAILURE) {
+ if (EG(exception) && exception) {
+ zend_exception_restore(TSRMLS_C);
free_alloca(lc_free, use_heap);
+ zend_error(E_ERROR, "Function %s(%s) threw an exception of type '%s'", ZEND_AUTOLOAD_FUNC_NAME, name, Z_OBJCE_P(EG(exception))->name);
return FAILURE;
}
+ zend_exception_restore(TSRMLS_C);
+ if (retval_ptr) {
+ zval_ptr_dtor(&retval_ptr);
+ }
- retval = zend_hash_find(EG(class_table), lc_name, lc_length, (void **) ce);
+ retval = zend_hash_find(EG(class_table), lc_name, name_length + 1, (void **) ce);
free_alloca(lc_free, use_heap);
return retval;
}
@@ -1467,6 +1435,7 @@ zend_class_entry *zend_fetch_class(const char *class_name, uint class_name_len,
{
zend_class_entry **pce;
int use_autoload = (fetch_type & ZEND_FETCH_CLASS_NO_AUTOLOAD) == 0;
+ int rt_ns_check = (fetch_type & ZEND_FETCH_CLASS_RT_NS_CHECK) ? 1 : 0;
int silent = (fetch_type & ZEND_FETCH_CLASS_SILENT) != 0;
fetch_type &= ZEND_FETCH_CLASS_MASK;
@@ -1500,14 +1469,36 @@ check_fetch_type:
break;
}
- if (zend_lookup_class_ex(class_name, class_name_len, use_autoload, &pce TSRMLS_CC) == FAILURE) {
+ if (zend_lookup_class_ex(class_name, class_name_len, (!rt_ns_check & use_autoload), &pce TSRMLS_CC) == FAILURE) {
+ if (rt_ns_check) {
+ /* Check if we have internal class with the same name */
+ char *php_name;
+ uint php_name_len;
+
+ php_name = zend_memrchr(class_name, ':', class_name_len);
+ if (php_name) {
+ php_name++;
+ php_name_len = class_name_len - (php_name - class_name);
+ php_name = zend_str_tolower_dup(php_name, php_name_len);
+ if (zend_hash_find(EG(class_table), php_name, php_name_len + 1, (void **) &pce) == SUCCESS &&
+ (*pce)->type == ZEND_INTERNAL_CLASS
+ ) {
+ efree(php_name);
+ return *pce;
+ }
+ efree(php_name);
+ }
+ }
if (use_autoload) {
- if (!silent && !EG(exception)) {
+ if (rt_ns_check && zend_lookup_class_ex(class_name, class_name_len, 1, &pce TSRMLS_CC) == SUCCESS) {
+ return *pce;
+ }
+ if (!silent) {
if (fetch_type == ZEND_FETCH_CLASS_INTERFACE) {
zend_error(E_ERROR, "Interface '%s' not found", class_name);
} else {
zend_error(E_ERROR, "Class '%s' not found", class_name);
- }
+ }
}
}
return NULL;
@@ -1617,20 +1608,8 @@ ZEND_API int zend_delete_global_variable(char *name, int name_len TSRMLS_DC) /*
ZEND_API void zend_rebuild_symbol_table(TSRMLS_D) /* {{{ */
{
zend_uint i;
- zend_execute_data *ex;
if (!EG(active_symbol_table)) {
-
- /* Search for last called user function */
- ex = EG(current_execute_data);
- while (ex && !ex->op_array) {
- ex = ex->prev_execute_data;
- }
- if (ex && ex->symbol_table) {
- EG(active_symbol_table) = ex->symbol_table;
- return;
- }
-
if (EG(symtable_cache_ptr)>=EG(symtable_cache)) {
/*printf("Cache hit! Reusing %x\n", symtable_cache[symtable_cache_ptr]);*/
EG(active_symbol_table) = *(EG(symtable_cache_ptr)--);
@@ -1639,24 +1618,24 @@ ZEND_API void zend_rebuild_symbol_table(TSRMLS_D) /* {{{ */
zend_hash_init(EG(active_symbol_table), 0, NULL, ZVAL_PTR_DTOR, 0);
/*printf("Cache miss! Initialized %x\n", EG(active_symbol_table));*/
}
- if (ex && ex->op_array) {
- ex->symbol_table = EG(active_symbol_table);
+ if (EG(current_execute_data) && EG(current_execute_data)->op_array) {
+ EG(current_execute_data)->symbol_table = EG(active_symbol_table);
- if (ex->op_array->this_var != -1 &&
- !ex->CVs[ex->op_array->this_var] &&
+ if (EG(current_execute_data)->op_array->this_var != -1 &&
+ !EG(current_execute_data)->CVs[EG(current_execute_data)->op_array->this_var] &&
EG(This)) {
- ex->CVs[ex->op_array->this_var] = (zval**)ex->CVs + ex->op_array->last_var + ex->op_array->this_var;
- *ex->CVs[ex->op_array->this_var] = EG(This);
+ EG(current_execute_data)->CVs[EG(current_execute_data)->op_array->this_var] = (zval**)EG(current_execute_data)->CVs + EG(current_execute_data)->op_array->last_var + EG(current_execute_data)->op_array->this_var;
+ *EG(current_execute_data)->CVs[EG(current_execute_data)->op_array->this_var] = EG(This);
}
- for (i = 0; i < ex->op_array->last_var; i++) {
- if (ex->CVs[i]) {
+ for (i = 0; i < EG(current_execute_data)->op_array->last_var; i++) {
+ if (EG(current_execute_data)->CVs[i]) {
zend_hash_quick_update(EG(active_symbol_table),
- ex->op_array->vars[i].name,
- ex->op_array->vars[i].name_len + 1,
- ex->op_array->vars[i].hash_value,
- (void**)ex->CVs[i],
+ EG(current_execute_data)->op_array->vars[i].name,
+ EG(current_execute_data)->op_array->vars[i].name_len + 1,
+ EG(current_execute_data)->op_array->vars[i].hash_value,
+ (void**)EG(current_execute_data)->CVs[i],
sizeof(zval*),
- (void**)&ex->CVs[i]);
+ (void**)&EG(current_execute_data)->CVs[i]);
}
}
}