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.c135
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)--);