diff options
Diffstat (limited to 'Zend/zend_execute_API.c')
-rw-r--r-- | Zend/zend_execute_API.c | 135 |
1 files changed, 92 insertions, 43 deletions
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 1cbbc1a0a1..63d20e1fe2 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -38,12 +38,15 @@ #ifdef HAVE_SYS_TIME_H #include <sys/time.h> #endif +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif ZEND_API void (*zend_execute_ex)(zend_execute_data *execute_data); ZEND_API void (*zend_execute_internal)(zend_execute_data *execute_data, zval *return_value); /* true globals */ -ZEND_API const zend_fcall_info empty_fcall_info = { 0, NULL, {{0}, {{0}}, {0}}, NULL, NULL, NULL, NULL, 0, 0 }; +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 }; #ifdef ZEND_WIN32 @@ -130,7 +133,7 @@ void init_executor(void) /* {{{ */ zend_init_fpu(); ZVAL_NULL(&EG(uninitialized_zval)); - ZVAL_NULL(&EG(error_zval)); + ZVAL_ERROR(&EG(error_zval)); /* destroys stack frame, therefore makes core dumps worthless */ #if 0&&ZEND_DEBUG original_sigsegv_handler = signal(SIGSEGV, zend_handle_sigsegv); @@ -169,9 +172,7 @@ void init_executor(void) /* {{{ */ zend_objects_store_init(&EG(objects_store), 1024); EG(full_tables_cleanup) = 0; -#ifdef ZEND_WIN32 EG(timed_out) = 0; -#endif EG(exception) = NULL; EG(prev_exception) = NULL; @@ -662,25 +663,17 @@ ZEND_API int zval_update_constant(zval *pp, zend_bool inline_change) /* {{{ */ } /* }}} */ -int call_user_function(HashTable *function_table, zval *object, zval *function_name, zval *retval_ptr, uint32_t param_count, zval params[]) /* {{{ */ -{ - return call_user_function_ex(function_table, object, function_name, retval_ptr, param_count, params, 1, NULL); -} -/* }}} */ - -int call_user_function_ex(HashTable *function_table, zval *object, zval *function_name, zval *retval_ptr, uint32_t param_count, zval params[], int no_separation, zend_array *symbol_table) /* {{{ */ +int _call_user_function_ex(zval *object, zval *function_name, zval *retval_ptr, uint32_t param_count, zval params[], int no_separation) /* {{{ */ { zend_fcall_info fci; fci.size = sizeof(fci); - fci.function_table = function_table; fci.object = object ? Z_OBJ_P(object) : NULL; ZVAL_COPY_VALUE(&fci.function_name, function_name); fci.retval = retval_ptr; fci.param_count = param_count; fci.params = params; fci.no_separation = (zend_bool) no_separation; - fci.symbol_table = symbol_table; return zend_call_function(&fci, NULL); } @@ -770,10 +763,12 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) / } func = fci_cache->function_handler; - call = zend_vm_stack_push_call_frame(ZEND_CALL_TOP_FUNCTION, - func, fci->param_count, fci_cache->called_scope, fci_cache->object); calling_scope = fci_cache->calling_scope; - fci->object = fci_cache->object; + fci->object = (func->common.fn_flags & ZEND_ACC_STATIC) ? + NULL : fci_cache->object; + + call = zend_vm_stack_push_call_frame(ZEND_CALL_TOP_FUNCTION, + func, fci->param_count, fci_cache->called_scope, fci->object); if (fci->object && (!EG(objects_store).object_buckets || !IS_OBJ_VALID(EG(objects_store).object_buckets[fci->object->handle]))) { @@ -843,10 +838,6 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) / } EG(scope) = calling_scope; - if (func->common.fn_flags & ZEND_ACC_STATIC) { - fci->object = NULL; - } - Z_OBJ(call->This) = fci->object; if (UNEXPECTED(func->op_array.fn_flags & ZEND_ACC_CLOSURE)) { ZEND_ASSERT(GC_TYPE((zend_object*)func->op_array.prototype) == IS_OBJECT); @@ -854,13 +845,10 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) / ZEND_ADD_CALL_FLAG(call, ZEND_CALL_CLOSURE); } - /* PHP-7 doesn't support symbol_table substitution for functions */ - ZEND_ASSERT(fci->symbol_table == NULL); - if (func->type == ZEND_USER_FUNCTION) { int call_via_handler = (func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) != 0; EG(scope) = func->common.scope; - call->symbol_table = fci->symbol_table; + call->symbol_table = NULL; if (EXPECTED((func->op_array.fn_flags & ZEND_ACC_GENERATOR) == 0)) { zend_init_execute_data(call, &func->op_array, fci->retval); zend_execute_ex(call); @@ -1028,9 +1016,7 @@ ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, const zval *k } fcall_info.size = sizeof(fcall_info); - fcall_info.function_table = EG(function_table); ZVAL_STR_COPY(&fcall_info.function_name, EG(autoload_func)->common.function_name); - fcall_info.symbol_table = NULL; fcall_info.retval = &local_retval; fcall_info.param_count = 1; fcall_info.params = args; @@ -1072,11 +1058,13 @@ ZEND_API zend_class_entry *zend_lookup_class(zend_string *name) /* {{{ */ ZEND_API zend_class_entry *zend_get_called_scope(zend_execute_data *ex) /* {{{ */ { while (ex) { - if (ex->called_scope) { - return ex->called_scope; + if (Z_TYPE(ex->This) == IS_OBJECT) { + return Z_OBJCE(ex->This); + } else if (Z_CE(ex->This)) { + return Z_CE(ex->This); } else if (ex->func) { if (ex->func->type != ZEND_INTERNAL_FUNCTION || ex->func->common.scope) { - return ex->called_scope; + return NULL; } } ex = ex->prev_execute_data; @@ -1088,11 +1076,11 @@ ZEND_API zend_class_entry *zend_get_called_scope(zend_execute_data *ex) /* {{{ * ZEND_API zend_object *zend_get_this_object(zend_execute_data *ex) /* {{{ */ { while (ex) { - if (Z_OBJ(ex->This)) { + if (Z_TYPE(ex->This) == IS_OBJECT) { return Z_OBJ(ex->This); } else if (ex->func) { if (ex->func->type != ZEND_INTERNAL_FUNCTION || ex->func->common.scope) { - return Z_OBJ(ex->This); + return NULL; } } ex = ex->prev_execute_data; @@ -1188,8 +1176,47 @@ ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name, } /* }}} */ -ZEND_API void zend_timeout(int dummy) /* {{{ */ +static void zend_set_timeout_ex(zend_long seconds, int reset_signals); + +ZEND_API ZEND_NORETURN void zend_timeout(int dummy) /* {{{ */ +{ + EG(timed_out) = 0; + zend_set_timeout_ex(0, 1); + zend_error_noreturn(E_ERROR, "Maximum execution time of %pd second%s exceeded", EG(timeout_seconds), EG(timeout_seconds) == 1 ? "" : "s"); +} +/* }}} */ + +#ifndef ZEND_WIN32 +static void zend_timeout_handler(int dummy) /* {{{ */ { +#ifndef ZTS + if (EG(timed_out)) { + /* Die on hard timeout */ + const char *error_filename = NULL; + uint error_lineno = 0; + char *log_buffer = NULL; + + if (zend_is_compiling()) { + error_filename = ZSTR_VAL(zend_get_compiled_filename()); + error_lineno = zend_get_compiled_lineno(); + } else if (zend_is_executing()) { + error_filename = zend_get_executed_filename(); + if (error_filename[0] == '[') { /* [no active file] */ + error_filename = NULL; + error_lineno = 0; + } else { + error_lineno = zend_get_executed_lineno(); + } + } + if (!error_filename) { + error_filename = "Unknown"; + } + + zend_spprintf(&log_buffer, 0, "\nFatal error: Maximum execution time of %pd+%pd seconds exceeded (terminated) in %s on line %d\n", EG(timeout_seconds), EG(hard_timeout), error_filename, error_lineno); + write(2, log_buffer, strlen(log_buffer)); + _exit(1); + } +#endif if (zend_on_timeout) { #ifdef ZEND_SIGNALS @@ -1204,9 +1231,17 @@ ZEND_API void zend_timeout(int dummy) /* {{{ */ zend_on_timeout(EG(timeout_seconds)); } - zend_error_noreturn(E_ERROR, "Maximum execution time of %pd second%s exceeded", EG(timeout_seconds), EG(timeout_seconds) == 1 ? "" : "s"); + EG(timed_out) = 1; + +#ifndef ZTS + if (EG(hard_timeout) > 0) { + /* Set hard timeout */ + zend_set_timeout_ex(EG(hard_timeout), 1); + } +#endif } /* }}} */ +#endif #ifdef ZEND_WIN32 VOID CALLBACK tq_timer_cb(PVOID arg, BOOLEAN timed_out) @@ -1229,11 +1264,9 @@ VOID CALLBACK tq_timer_cb(PVOID arg, BOOLEAN timed_out) #define SIGPROF 27 #endif -void zend_set_timeout(zend_long seconds, int reset_signals) /* {{{ */ +static void zend_set_timeout_ex(zend_long seconds, int reset_signals) /* {{{ */ { - EG(timeout_seconds) = seconds; - #ifdef ZEND_WIN32 if(!seconds) { return; @@ -1244,7 +1277,6 @@ void zend_set_timeout(zend_long seconds, int reset_signals) /* {{{ */ delete and recreate. */ if (NULL != tq_timer) { if (!DeleteTimerQueueTimer(NULL, tq_timer, NULL)) { - EG(timed_out) = 0; tq_timer = NULL; zend_error_noreturn(E_ERROR, "Could not delete queued timer"); return; @@ -1254,12 +1286,10 @@ void zend_set_timeout(zend_long seconds, int reset_signals) /* {{{ */ /* XXX passing NULL means the default timer queue provided by the system is used */ if (!CreateTimerQueueTimer(&tq_timer, NULL, (WAITORTIMERCALLBACK)tq_timer_cb, (VOID*)&EG(timed_out), seconds*1000, 0, WT_EXECUTEONLYONCE)) { - EG(timed_out) = 0; tq_timer = NULL; zend_error_noreturn(E_ERROR, "Could not queue new timer"); return; } - EG(timed_out) = 0; #else # ifdef HAVE_SETITIMER { @@ -1282,15 +1312,23 @@ void zend_set_timeout(zend_long seconds, int reset_signals) /* {{{ */ if (reset_signals) { # ifdef ZEND_SIGNALS - zend_signal(signo, zend_timeout); + zend_signal(signo, zend_timeout_handler); # else sigset_t sigset; - - signal(signo, zend_timeout); +# ifdef HAVE_SIGACTION + struct sigaction act; + + act.sa_handler = zend_timeout_handler; + sigemptyset(&act.sa_mask); + act.sa_flags = SA_RESETHAND | SA_NODEFER; + sigaction(signo, &act, NULL); +# else + signal(signo, zend_timeout_handler); +# endif /* HAVE_SIGACTION */ sigemptyset(&sigset); sigaddset(&sigset, signo); sigprocmask(SIG_UNBLOCK, &sigset, NULL); -# endif +# endif /* ZEND_SIGNALS */ } } # endif /* HAVE_SETITIMER */ @@ -1298,6 +1336,15 @@ void zend_set_timeout(zend_long seconds, int reset_signals) /* {{{ */ } /* }}} */ +void zend_set_timeout(zend_long seconds, int reset_signals) /* {{{ */ +{ + + EG(timeout_seconds) = seconds; + zend_set_timeout_ex(seconds, reset_signals); + EG(timed_out) = 0; +} +/* }}} */ + void zend_unset_timeout(void) /* {{{ */ { #ifdef ZEND_WIN32 @@ -1325,6 +1372,7 @@ void zend_unset_timeout(void) /* {{{ */ #endif } # endif + EG(timed_out) = 0; #endif } /* }}} */ @@ -1488,6 +1536,7 @@ ZEND_API zend_array *zend_rebuild_symbol_table(void) /* {{{ */ return ex->symbol_table; } + ZEND_ADD_CALL_FLAG(ex, ZEND_CALL_FREE_SYMBOL_TABLE); if (EG(symtable_cache_ptr) >= EG(symtable_cache)) { /*printf("Cache hit! Reusing %x\n", symtable_cache[symtable_cache_ptr]);*/ symbol_table = ex->symbol_table = *(EG(symtable_cache_ptr)--); |