1/*
2   +----------------------------------------------------------------------+
3   | Zend Engine                                                          |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 1998-2016 Zend Technologies Ltd. (http://www.zend.com) |
6   +----------------------------------------------------------------------+
7   | This source file is subject to version 2.00 of the Zend license,     |
8   | that is bundled with this package in the file LICENSE, and is        |
9   | available through the world-wide-web at the following url:           |
10   | http://www.zend.com/license/2_00.txt.                                |
11   | If you did not receive a copy of the Zend license and are unable to  |
12   | obtain it through the world-wide-web, please send a note to          |
13   | license@zend.com so we can mail you a copy immediately.              |
14   +----------------------------------------------------------------------+
15   | Authors: Andi Gutmans <andi@zend.com>                                |
16   |          Zeev Suraski <zeev@zend.com>                                |
17   |          Dmitry Stogov <dmitry@zend.com>                             |
18   +----------------------------------------------------------------------+
19*/
20
21/* $Id$ */
22
23#include <stdio.h>
24#include <signal.h>
25
26#include "zend.h"
27#include "zend_compile.h"
28#include "zend_execute.h"
29#include "zend_API.h"
30#include "zend_stack.h"
31#include "zend_constants.h"
32#include "zend_extensions.h"
33#include "zend_exceptions.h"
34#include "zend_closures.h"
35#include "zend_generators.h"
36#include "zend_vm.h"
37#include "zend_float.h"
38#ifdef HAVE_SYS_TIME_H
39#include <sys/time.h>
40#endif
41#ifdef HAVE_UNISTD_H
42#include <unistd.h>
43#endif
44
45ZEND_API void (*zend_execute_ex)(zend_execute_data *execute_data);
46ZEND_API void (*zend_execute_internal)(zend_execute_data *execute_data, zval *return_value);
47
48/* true globals */
49ZEND_API const zend_fcall_info empty_fcall_info = { 0, {{0}, {{0}}, {0}}, NULL, NULL, NULL, 0, 0 };
50ZEND_API const zend_fcall_info_cache empty_fcall_info_cache = { 0, NULL, NULL, NULL, NULL };
51
52#ifdef ZEND_WIN32
53ZEND_TLS HANDLE tq_timer = NULL;
54#endif
55
56#if 0&&ZEND_DEBUG
57static void (*original_sigsegv_handler)(int);
58static void zend_handle_sigsegv(int dummy) /* {{{ */
59{
60	fflush(stdout);
61	fflush(stderr);
62	if (original_sigsegv_handler == zend_handle_sigsegv) {
63		signal(SIGSEGV, original_sigsegv_handler);
64	} else {
65		signal(SIGSEGV, SIG_DFL);
66	}
67	{
68
69		fprintf(stderr, "SIGSEGV caught on opcode %d on opline %d of %s() at %s:%d\n\n",
70				active_opline->opcode,
71				active_opline-EG(active_op_array)->opcodes,
72				get_active_function_name(),
73				zend_get_executed_filename(),
74				zend_get_executed_lineno());
75/* See http://support.microsoft.com/kb/190351 */
76#ifdef ZEND_WIN32
77		fflush(stderr);
78#endif
79	}
80	if (original_sigsegv_handler!=zend_handle_sigsegv) {
81		original_sigsegv_handler(dummy);
82	}
83}
84/* }}} */
85#endif
86
87static void zend_extension_activator(zend_extension *extension) /* {{{ */
88{
89	if (extension->activate) {
90		extension->activate();
91	}
92}
93/* }}} */
94
95static void zend_extension_deactivator(zend_extension *extension) /* {{{ */
96{
97	if (extension->deactivate) {
98		extension->deactivate();
99	}
100}
101/* }}} */
102
103static int clean_non_persistent_function(zval *zv) /* {{{ */
104{
105	zend_function *function = Z_PTR_P(zv);
106	return (function->type == ZEND_INTERNAL_FUNCTION) ? ZEND_HASH_APPLY_STOP : ZEND_HASH_APPLY_REMOVE;
107}
108/* }}} */
109
110ZEND_API int clean_non_persistent_function_full(zval *zv) /* {{{ */
111{
112	zend_function *function = Z_PTR_P(zv);
113	return (function->type == ZEND_INTERNAL_FUNCTION) ? ZEND_HASH_APPLY_KEEP : ZEND_HASH_APPLY_REMOVE;
114}
115/* }}} */
116
117static int clean_non_persistent_class(zval *zv) /* {{{ */
118{
119	zend_class_entry *ce = Z_PTR_P(zv);
120	return (ce->type == ZEND_INTERNAL_CLASS) ? ZEND_HASH_APPLY_STOP : ZEND_HASH_APPLY_REMOVE;
121}
122/* }}} */
123
124ZEND_API int clean_non_persistent_class_full(zval *zv) /* {{{ */
125{
126	zend_class_entry *ce = Z_PTR_P(zv);
127	return (ce->type == ZEND_INTERNAL_CLASS) ? ZEND_HASH_APPLY_KEEP : ZEND_HASH_APPLY_REMOVE;
128}
129/* }}} */
130
131void init_executor(void) /* {{{ */
132{
133	zend_init_fpu();
134
135	ZVAL_NULL(&EG(uninitialized_zval));
136	ZVAL_ERROR(&EG(error_zval));
137/* destroys stack frame, therefore makes core dumps worthless */
138#if 0&&ZEND_DEBUG
139	original_sigsegv_handler = signal(SIGSEGV, zend_handle_sigsegv);
140#endif
141
142	EG(symtable_cache_ptr) = EG(symtable_cache) - 1;
143	EG(symtable_cache_limit) = EG(symtable_cache) + SYMTABLE_CACHE_SIZE - 1;
144	EG(no_extensions) = 0;
145
146	EG(function_table) = CG(function_table);
147	EG(class_table) = CG(class_table);
148
149	EG(in_autoload) = NULL;
150	EG(autoload_func) = NULL;
151	EG(error_handling) = EH_NORMAL;
152
153	zend_vm_stack_init();
154
155	zend_hash_init(&EG(symbol_table), 64, NULL, ZVAL_PTR_DTOR, 0);
156	EG(valid_symbol_table) = 1;
157
158	zend_llist_apply(&zend_extensions, (llist_apply_func_t) zend_extension_activator);
159
160	zend_hash_init(&EG(included_files), 8, NULL, NULL, 0);
161
162	EG(ticks_count) = 0;
163
164	ZVAL_UNDEF(&EG(user_error_handler));
165
166	EG(current_execute_data) = NULL;
167
168	zend_stack_init(&EG(user_error_handlers_error_reporting), sizeof(int));
169	zend_stack_init(&EG(user_error_handlers), sizeof(zval));
170	zend_stack_init(&EG(user_exception_handlers), sizeof(zval));
171
172	zend_objects_store_init(&EG(objects_store), 1024);
173
174	EG(full_tables_cleanup) = 0;
175	EG(timed_out) = 0;
176
177	EG(exception) = NULL;
178	EG(prev_exception) = NULL;
179
180	EG(fake_scope) = NULL;
181
182	EG(ht_iterators_count) = sizeof(EG(ht_iterators_slots)) / sizeof(HashTableIterator);
183	EG(ht_iterators_used) = 0;
184	EG(ht_iterators) = EG(ht_iterators_slots);
185	memset(EG(ht_iterators), 0, sizeof(EG(ht_iterators_slots)));
186
187	EG(active) = 1;
188}
189/* }}} */
190
191static int zval_call_destructor(zval *zv) /* {{{ */
192{
193	if (Z_TYPE_P(zv) == IS_INDIRECT) {
194		zv = Z_INDIRECT_P(zv);
195	}
196	if (Z_TYPE_P(zv) == IS_OBJECT && Z_REFCOUNT_P(zv) == 1) {
197		return ZEND_HASH_APPLY_REMOVE;
198	} else {
199		return ZEND_HASH_APPLY_KEEP;
200	}
201}
202/* }}} */
203
204static void zend_unclean_zval_ptr_dtor(zval *zv) /* {{{ */
205{
206	if (Z_TYPE_P(zv) == IS_INDIRECT) {
207		zv = Z_INDIRECT_P(zv);
208	}
209	i_zval_ptr_dtor(zv ZEND_FILE_LINE_CC);
210}
211/* }}} */
212
213static void zend_throw_or_error(int fetch_type, zend_class_entry *exception_ce, const char *format, ...) /* {{{ */
214{
215	va_list va;
216	char *message = NULL;
217
218	va_start(va, format);
219	zend_vspprintf(&message, 0, format, va);
220
221	if (fetch_type & ZEND_FETCH_CLASS_EXCEPTION) {
222		zend_throw_error(exception_ce, "%s", message);
223	} else {
224		zend_error(E_ERROR, "%s", message);
225	}
226
227	efree(message);
228	va_end(va);
229}
230/* }}} */
231
232void shutdown_destructors(void) /* {{{ */
233{
234	if (CG(unclean_shutdown)) {
235		EG(symbol_table).pDestructor = zend_unclean_zval_ptr_dtor;
236	}
237	zend_try {
238		uint32_t symbols;
239		do {
240			symbols = zend_hash_num_elements(&EG(symbol_table));
241			zend_hash_reverse_apply(&EG(symbol_table), (apply_func_t) zval_call_destructor);
242		} while (symbols != zend_hash_num_elements(&EG(symbol_table)));
243		zend_objects_store_call_destructors(&EG(objects_store));
244	} zend_catch {
245		/* if we couldn't destruct cleanly, mark all objects as destructed anyway */
246		zend_objects_store_mark_destructed(&EG(objects_store));
247	} zend_end_try();
248}
249/* }}} */
250
251void shutdown_executor(void) /* {{{ */
252{
253	zend_function *func;
254	zend_class_entry *ce;
255
256	zend_try {
257
258/* Removed because this can not be safely done, e.g. in this situation:
259   Object 1 creates object 2
260   Object 3 holds reference to object 2.
261   Now when 1 and 2 are destroyed, 3 can still access 2 in its destructor, with
262   very problematic results */
263/* 		zend_objects_store_call_destructors(&EG(objects_store)); */
264
265/* Moved after symbol table cleaners, because  some of the cleaners can call
266   destructors, which would use EG(symtable_cache_ptr) and thus leave leaks */
267/*		while (EG(symtable_cache_ptr)>=EG(symtable_cache)) {
268			zend_hash_destroy(*EG(symtable_cache_ptr));
269			efree(*EG(symtable_cache_ptr));
270			EG(symtable_cache_ptr)--;
271		}
272*/
273		zend_llist_apply(&zend_extensions, (llist_apply_func_t) zend_extension_deactivator);
274
275		if (CG(unclean_shutdown)) {
276			EG(symbol_table).pDestructor = zend_unclean_zval_ptr_dtor;
277		}
278		zend_hash_graceful_reverse_destroy(&EG(symbol_table));
279	} zend_end_try();
280	EG(valid_symbol_table) = 0;
281
282	zend_try {
283		zval *zeh;
284		/* remove error handlers before destroying classes and functions,
285		 * so that if handler used some class, crash would not happen */
286		if (Z_TYPE(EG(user_error_handler)) != IS_UNDEF) {
287			zeh = &EG(user_error_handler);
288			zval_ptr_dtor(zeh);
289			ZVAL_UNDEF(&EG(user_error_handler));
290		}
291
292		if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) {
293			zeh = &EG(user_exception_handler);
294			zval_ptr_dtor(zeh);
295			ZVAL_UNDEF(&EG(user_exception_handler));
296		}
297
298		zend_stack_clean(&EG(user_error_handlers_error_reporting), NULL, 1);
299		zend_stack_clean(&EG(user_error_handlers), (void (*)(void *))ZVAL_PTR_DTOR, 1);
300		zend_stack_clean(&EG(user_exception_handlers), (void (*)(void *))ZVAL_PTR_DTOR, 1);
301	} zend_end_try();
302
303	zend_try {
304		/* Cleanup static data for functions and arrays.
305		 * We need a separate cleanup stage because of the following problem:
306		 * Suppose we destroy class X, which destroys the class's function table,
307		 * and in the function table we have function foo() that has static $bar.
308		 * Now if an object of class X is assigned to $bar, its destructor will be
309		 * called and will fail since X's function table is in mid-destruction.
310		 * So we want first of all to clean up all data and then move to tables destruction.
311		 * Note that only run-time accessed data need to be cleaned up, pre-defined data can
312		 * not contain objects and thus are not probelmatic */
313		if (EG(full_tables_cleanup)) {
314			ZEND_HASH_FOREACH_PTR(EG(function_table), func) {
315				if (func->type == ZEND_USER_FUNCTION) {
316					zend_cleanup_op_array_data((zend_op_array *) func);
317				}
318			} ZEND_HASH_FOREACH_END();
319			ZEND_HASH_REVERSE_FOREACH_PTR(EG(class_table), ce) {
320				if (ce->type == ZEND_USER_CLASS) {
321					zend_cleanup_user_class_data(ce);
322				} else {
323					zend_cleanup_internal_class_data(ce);
324				}
325			} ZEND_HASH_FOREACH_END();
326		} else {
327			ZEND_HASH_REVERSE_FOREACH_PTR(EG(function_table), func) {
328				if (func->type != ZEND_USER_FUNCTION) {
329					break;
330				}
331				zend_cleanup_op_array_data((zend_op_array *) func);
332			} ZEND_HASH_FOREACH_END();
333			ZEND_HASH_REVERSE_FOREACH_PTR(EG(class_table), ce) {
334				if (ce->type != ZEND_USER_CLASS) {
335					break;
336				}
337				zend_cleanup_user_class_data(ce);
338			} ZEND_HASH_FOREACH_END();
339			zend_cleanup_internal_classes();
340		}
341	} zend_end_try();
342
343	zend_try {
344		zend_llist_destroy(&CG(open_files));
345	} zend_end_try();
346
347	zend_try {
348		zend_close_rsrc_list(&EG(regular_list));
349	} zend_end_try();
350
351#if ZEND_DEBUG
352	if (GC_G(gc_enabled) && !CG(unclean_shutdown)) {
353		gc_collect_cycles();
354	}
355#endif
356
357	zend_try {
358		zend_objects_store_free_object_storage(&EG(objects_store));
359
360		zend_vm_stack_destroy();
361
362		/* Destroy all op arrays */
363		if (EG(full_tables_cleanup)) {
364			zend_hash_reverse_apply(EG(function_table), clean_non_persistent_function_full);
365			zend_hash_reverse_apply(EG(class_table), clean_non_persistent_class_full);
366		} else {
367			zend_hash_reverse_apply(EG(function_table), clean_non_persistent_function);
368			zend_hash_reverse_apply(EG(class_table), clean_non_persistent_class);
369		}
370
371		while (EG(symtable_cache_ptr)>=EG(symtable_cache)) {
372			zend_hash_destroy(*EG(symtable_cache_ptr));
373			FREE_HASHTABLE(*EG(symtable_cache_ptr));
374			EG(symtable_cache_ptr)--;
375		}
376	} zend_end_try();
377
378	zend_try {
379		clean_non_persistent_constants();
380	} zend_end_try();
381
382	zend_try {
383#if 0&&ZEND_DEBUG
384	signal(SIGSEGV, original_sigsegv_handler);
385#endif
386
387		zend_hash_destroy(&EG(included_files));
388
389		zend_stack_destroy(&EG(user_error_handlers_error_reporting));
390		zend_stack_destroy(&EG(user_error_handlers));
391		zend_stack_destroy(&EG(user_exception_handlers));
392		zend_objects_store_destroy(&EG(objects_store));
393		if (EG(in_autoload)) {
394			zend_hash_destroy(EG(in_autoload));
395			FREE_HASHTABLE(EG(in_autoload));
396		}
397	} zend_end_try();
398
399	zend_shutdown_fpu();
400
401#if ZEND_DEBUG
402	if (EG(ht_iterators_used) && !CG(unclean_shutdown)) {
403		zend_error(E_WARNING, "Leaked %" PRIu32 " hashtable iterators", EG(ht_iterators_used));
404	}
405#endif
406
407	EG(ht_iterators_used) = 0;
408	if (EG(ht_iterators) != EG(ht_iterators_slots)) {
409		efree(EG(ht_iterators));
410	}
411
412	EG(active) = 0;
413}
414/* }}} */
415
416/* return class name and "::" or "". */
417ZEND_API const char *get_active_class_name(const char **space) /* {{{ */
418{
419	zend_function *func;
420
421	if (!zend_is_executing()) {
422		if (space) {
423			*space = "";
424		}
425		return "";
426	}
427
428	func = EG(current_execute_data)->func;
429	switch (func->type) {
430		case ZEND_USER_FUNCTION:
431		case ZEND_INTERNAL_FUNCTION:
432		{
433			zend_class_entry *ce = func->common.scope;
434
435			if (space) {
436				*space = ce ? "::" : "";
437			}
438			return ce ? ZSTR_VAL(ce->name) : "";
439		}
440		default:
441			if (space) {
442				*space = "";
443			}
444			return "";
445	}
446}
447/* }}} */
448
449ZEND_API const char *get_active_function_name(void) /* {{{ */
450{
451	zend_function *func;
452
453	if (!zend_is_executing()) {
454		return NULL;
455	}
456	func = EG(current_execute_data)->func;
457	switch (func->type) {
458		case ZEND_USER_FUNCTION: {
459				zend_string *function_name = func->common.function_name;
460
461				if (function_name) {
462					return ZSTR_VAL(function_name);
463				} else {
464					return "main";
465				}
466			}
467			break;
468		case ZEND_INTERNAL_FUNCTION:
469			return ZSTR_VAL(func->common.function_name);
470			break;
471		default:
472			return NULL;
473	}
474}
475/* }}} */
476
477ZEND_API const char *zend_get_executed_filename(void) /* {{{ */
478{
479	zend_execute_data *ex = EG(current_execute_data);
480
481	while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) {
482		ex = ex->prev_execute_data;
483	}
484	if (ex) {
485		return ZSTR_VAL(ex->func->op_array.filename);
486	} else {
487		return "[no active file]";
488	}
489}
490/* }}} */
491
492ZEND_API zend_string *zend_get_executed_filename_ex(void) /* {{{ */
493{
494	zend_execute_data *ex = EG(current_execute_data);
495
496	while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) {
497		ex = ex->prev_execute_data;
498	}
499	if (ex) {
500		return ex->func->op_array.filename;
501	} else {
502		return NULL;
503	}
504}
505/* }}} */
506
507ZEND_API uint zend_get_executed_lineno(void) /* {{{ */
508{
509	zend_execute_data *ex = EG(current_execute_data);
510
511	while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) {
512		ex = ex->prev_execute_data;
513	}
514	if (ex) {
515		if (EG(exception) && ex->opline->opcode == ZEND_HANDLE_EXCEPTION &&
516		    ex->opline->lineno == 0 && EG(opline_before_exception)) {
517			return EG(opline_before_exception)->lineno;
518		}
519		return ex->opline->lineno;
520	} else {
521		return 0;
522	}
523}
524/* }}} */
525
526ZEND_API zend_class_entry *zend_get_executed_scope(void) /* {{{ */
527{
528	zend_execute_data *ex = EG(current_execute_data);
529
530	while (1) {
531		if (!ex) {
532			return NULL;
533		} else if (ex->func && (ZEND_USER_CODE(ex->func->type) || ex->func->common.scope)) {
534			return ex->func->common.scope;
535		}
536		ex = ex->prev_execute_data;
537	}
538}
539/* }}} */
540
541ZEND_API zend_bool zend_is_executing(void) /* {{{ */
542{
543	return EG(current_execute_data) != 0;
544}
545/* }}} */
546
547ZEND_API void _zval_ptr_dtor(zval *zval_ptr ZEND_FILE_LINE_DC) /* {{{ */
548{
549	i_zval_ptr_dtor(zval_ptr ZEND_FILE_LINE_RELAY_CC);
550}
551/* }}} */
552
553ZEND_API void _zval_internal_ptr_dtor(zval *zval_ptr ZEND_FILE_LINE_DC) /* {{{ */
554{
555	if (Z_REFCOUNTED_P(zval_ptr)) {
556		Z_DELREF_P(zval_ptr);
557		if (Z_REFCOUNT_P(zval_ptr) == 0) {
558			_zval_internal_dtor_for_ptr(zval_ptr ZEND_FILE_LINE_CC);
559		}
560	}
561}
562/* }}} */
563
564ZEND_API int zval_update_constant_ex(zval *p, zend_class_entry *scope) /* {{{ */
565{
566	zval *const_value;
567	char *colon;
568	zend_bool inline_change;
569
570	if (Z_TYPE_P(p) == IS_CONSTANT) {
571		if (IS_CONSTANT_VISITED(p)) {
572			zend_throw_error(NULL, "Cannot declare self-referencing constant '%s'", Z_STRVAL_P(p));
573			return FAILURE;
574		}
575		inline_change = (Z_TYPE_FLAGS_P(p) & IS_TYPE_IMMUTABLE) == 0;
576		SEPARATE_ZVAL_NOREF(p);
577		MARK_CONSTANT_VISITED(p);
578		if (Z_CONST_FLAGS_P(p) & IS_CONSTANT_CLASS) {
579			ZEND_ASSERT(EG(current_execute_data));
580			if (inline_change) {
581				zend_string_release(Z_STR_P(p));
582			}
583			if (scope && scope->name) {
584				ZVAL_STR_COPY(p, scope->name);
585			} else {
586				ZVAL_EMPTY_STRING(p);
587			}
588		} else if (UNEXPECTED((const_value = zend_get_constant_ex(Z_STR_P(p), scope, Z_CONST_FLAGS_P(p))) == NULL)) {
589			char *actual = Z_STRVAL_P(p);
590
591			if (UNEXPECTED(EG(exception))) {
592				RESET_CONSTANT_VISITED(p);
593				return FAILURE;
594			} else if ((colon = (char*)zend_memrchr(Z_STRVAL_P(p), ':', Z_STRLEN_P(p)))) {
595				zend_throw_error(NULL, "Undefined class constant '%s'", Z_STRVAL_P(p));
596				RESET_CONSTANT_VISITED(p);
597				return FAILURE;
598			} else {
599				zend_string *save = Z_STR_P(p);
600				char *slash;
601				size_t actual_len = Z_STRLEN_P(p);
602				if ((Z_CONST_FLAGS_P(p) & IS_CONSTANT_UNQUALIFIED) && (slash = (char *)zend_memrchr(actual, '\\', actual_len))) {
603					actual = slash + 1;
604					actual_len -= (actual - Z_STRVAL_P(p));
605					if (inline_change) {
606						zend_string *s = zend_string_init(actual, actual_len, 0);
607						Z_STR_P(p) = s;
608						Z_TYPE_FLAGS_P(p) = IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE;
609					}
610				}
611				if ((Z_CONST_FLAGS_P(p) & IS_CONSTANT_UNQUALIFIED) == 0) {
612					zend_throw_error(NULL, "Undefined constant '%s'", ZSTR_VAL(save));
613					if (inline_change) {
614						zend_string_release(save);
615					}
616					RESET_CONSTANT_VISITED(p);
617					return FAILURE;
618				} else {
619					zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",  actual,  actual);
620					if (!inline_change) {
621						ZVAL_STRINGL(p, actual, actual_len);
622					} else {
623						Z_TYPE_INFO_P(p) = Z_REFCOUNTED_P(p) ?
624							IS_STRING_EX : IS_INTERNED_STRING_EX;
625						if (save && ZSTR_VAL(save) != actual) {
626							zend_string_release(save);
627						}
628					}
629				}
630			}
631		} else {
632			if (inline_change) {
633				zend_string_release(Z_STR_P(p));
634			}
635			ZVAL_COPY_VALUE(p, const_value);
636			zval_opt_copy_ctor(p);
637		}
638	} else if (Z_TYPE_P(p) == IS_CONSTANT_AST) {
639		zval tmp;
640
641		inline_change = (Z_TYPE_FLAGS_P(p) & IS_TYPE_IMMUTABLE) == 0;
642		if (UNEXPECTED(zend_ast_evaluate(&tmp, Z_ASTVAL_P(p), scope) != SUCCESS)) {
643			return FAILURE;
644		}
645		if (inline_change) {
646			zval_ptr_dtor(p);
647		}
648		ZVAL_COPY_VALUE(p, &tmp);
649	}
650	return SUCCESS;
651}
652/* }}} */
653
654ZEND_API int zval_update_constant(zval *pp) /* {{{ */
655{
656	return zval_update_constant_ex(pp, EG(current_execute_data) ? zend_get_executed_scope() : CG(active_class_entry));
657}
658/* }}} */
659
660int _call_user_function_ex(zval *object, zval *function_name, zval *retval_ptr, uint32_t param_count, zval params[], int no_separation) /* {{{ */
661{
662	zend_fcall_info fci;
663
664	fci.size = sizeof(fci);
665	fci.object = object ? Z_OBJ_P(object) : NULL;
666	ZVAL_COPY_VALUE(&fci.function_name, function_name);
667	fci.retval = retval_ptr;
668	fci.param_count = param_count;
669	fci.params = params;
670	fci.no_separation = (zend_bool) no_separation;
671
672	return zend_call_function(&fci, NULL);
673}
674/* }}} */
675
676int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) /* {{{ */
677{
678	uint32_t i;
679	zend_execute_data *call, dummy_execute_data;
680	zend_fcall_info_cache fci_cache_local;
681	zend_function *func;
682
683	ZVAL_UNDEF(fci->retval);
684
685	if (!EG(active)) {
686		return FAILURE; /* executor is already inactive */
687	}
688
689	if (EG(exception)) {
690		return FAILURE; /* we would result in an instable executor otherwise */
691	}
692
693	switch (fci->size) {
694		case sizeof(zend_fcall_info):
695			break; /* nothing to do currently */
696		default:
697			zend_error_noreturn(E_CORE_ERROR, "Corrupted fcall_info provided to zend_call_function()");
698			break;
699	}
700
701	/* Initialize execute_data */
702	if (!EG(current_execute_data)) {
703		/* This only happens when we're called outside any execute()'s
704		 * It shouldn't be strictly necessary to NULL execute_data out,
705		 * but it may make bugs easier to spot
706		 */
707		memset(&dummy_execute_data, 0, sizeof(zend_execute_data));
708		EG(current_execute_data) = &dummy_execute_data;
709	} else if (EG(current_execute_data)->func &&
710	           ZEND_USER_CODE(EG(current_execute_data)->func->common.type) &&
711	           EG(current_execute_data)->opline->opcode != ZEND_DO_FCALL &&
712	           EG(current_execute_data)->opline->opcode != ZEND_DO_ICALL &&
713	           EG(current_execute_data)->opline->opcode != ZEND_DO_UCALL &&
714	           EG(current_execute_data)->opline->opcode != ZEND_DO_FCALL_BY_NAME) {
715		/* Insert fake frame in case of include or magic calls */
716		dummy_execute_data = *EG(current_execute_data);
717		dummy_execute_data.prev_execute_data = EG(current_execute_data);
718		dummy_execute_data.call = NULL;
719		dummy_execute_data.opline = NULL;
720		dummy_execute_data.func = NULL;
721		EG(current_execute_data) = &dummy_execute_data;
722	}
723
724	if (!fci_cache || !fci_cache->initialized) {
725		zend_string *callable_name;
726		char *error = NULL;
727
728		if (!fci_cache) {
729			fci_cache = &fci_cache_local;
730		}
731
732		if (!zend_is_callable_ex(&fci->function_name, fci->object, IS_CALLABLE_CHECK_SILENT, &callable_name, fci_cache, &error)) {
733			if (error) {
734				zend_error(E_WARNING, "Invalid callback %s, %s", ZSTR_VAL(callable_name), error);
735				efree(error);
736			}
737			if (callable_name) {
738				zend_string_release(callable_name);
739			}
740			if (EG(current_execute_data) == &dummy_execute_data) {
741				EG(current_execute_data) = dummy_execute_data.prev_execute_data;
742			}
743			return FAILURE;
744		} else if (error) {
745			/* Capitalize the first latter of the error message */
746			if (error[0] >= 'a' && error[0] <= 'z') {
747				error[0] += ('A' - 'a');
748			}
749			zend_error(E_DEPRECATED, "%s", error);
750			efree(error);
751		}
752		zend_string_release(callable_name);
753	}
754
755	func = fci_cache->function_handler;
756	fci->object = (func->common.fn_flags & ZEND_ACC_STATIC) ?
757		NULL : fci_cache->object;
758
759	call = zend_vm_stack_push_call_frame(ZEND_CALL_TOP_FUNCTION,
760		func, fci->param_count, fci_cache->called_scope, fci->object);
761	if (fci->object &&
762	    (!EG(objects_store).object_buckets ||
763	     !IS_OBJ_VALID(EG(objects_store).object_buckets[fci->object->handle]))) {
764		if (EG(current_execute_data) == &dummy_execute_data) {
765			EG(current_execute_data) = dummy_execute_data.prev_execute_data;
766		}
767		return FAILURE;
768	}
769
770	if (func->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) {
771		if (func->common.fn_flags & ZEND_ACC_ABSTRACT) {
772			zend_throw_error(NULL, "Cannot call abstract method %s::%s()", ZSTR_VAL(func->common.scope->name), ZSTR_VAL(func->common.function_name));
773			if (EG(current_execute_data) == &dummy_execute_data) {
774				EG(current_execute_data) = dummy_execute_data.prev_execute_data;
775			}
776			return FAILURE;
777		}
778		if (func->common.fn_flags & ZEND_ACC_DEPRECATED) {
779 			zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated",
780				func->common.scope ? ZSTR_VAL(func->common.scope->name) : "",
781				func->common.scope ? "::" : "",
782				ZSTR_VAL(func->common.function_name));
783		}
784	}
785
786	for (i=0; i<fci->param_count; i++) {
787		zval *param;
788		zval *arg = &fci->params[i];
789
790		if (ARG_SHOULD_BE_SENT_BY_REF(func, i + 1)) {
791			if (UNEXPECTED(!Z_ISREF_P(arg))) {
792				if (fci->no_separation &&
793					!ARG_MAY_BE_SENT_BY_REF(func, i + 1)) {
794					if (i) {
795						/* hack to clean up the stack */
796						ZEND_CALL_NUM_ARGS(call) = i;
797						zend_vm_stack_free_args(call);
798					}
799					zend_vm_stack_free_call_frame(call);
800
801					zend_error(E_WARNING, "Parameter %d to %s%s%s() expected to be a reference, value given",
802						i+1,
803						func->common.scope ? ZSTR_VAL(func->common.scope->name) : "",
804						func->common.scope ? "::" : "",
805						ZSTR_VAL(func->common.function_name));
806					if (EG(current_execute_data) == &dummy_execute_data) {
807						EG(current_execute_data) = dummy_execute_data.prev_execute_data;
808					}
809					return FAILURE;
810				}
811
812				ZVAL_NEW_REF(arg, arg);
813			}
814			Z_ADDREF_P(arg);
815		} else {
816			if (Z_ISREF_P(arg) &&
817			    !(func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
818				/* don't separate references for __call */
819				arg = Z_REFVAL_P(arg);
820			}
821			if (Z_OPT_REFCOUNTED_P(arg)) {
822				Z_ADDREF_P(arg);
823			}
824		}
825		param = ZEND_CALL_ARG(call, i+1);
826		ZVAL_COPY_VALUE(param, arg);
827	}
828
829	if (UNEXPECTED(func->op_array.fn_flags & ZEND_ACC_CLOSURE)) {
830		ZEND_ASSERT(GC_TYPE((zend_object*)func->op_array.prototype) == IS_OBJECT);
831		GC_REFCOUNT((zend_object*)func->op_array.prototype)++;
832		ZEND_ADD_CALL_FLAG(call, ZEND_CALL_CLOSURE);
833	}
834
835	if (func->type == ZEND_USER_FUNCTION) {
836		int call_via_handler = (func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) != 0;
837		if (EXPECTED((func->op_array.fn_flags & ZEND_ACC_GENERATOR) == 0)) {
838			zend_init_execute_data(call, &func->op_array, fci->retval);
839			zend_execute_ex(call);
840		} else {
841			zend_generator_create_zval(call, &func->op_array, fci->retval);
842		}
843		if (call_via_handler) {
844			/* We must re-initialize function again */
845			fci_cache->initialized = 0;
846		}
847	} else if (func->type == ZEND_INTERNAL_FUNCTION) {
848		int call_via_handler = (func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) != 0;
849		ZVAL_NULL(fci->retval);
850		call->prev_execute_data = EG(current_execute_data);
851		call->return_value = NULL; /* this is not a constructor call */
852		EG(current_execute_data) = call;
853		if (EXPECTED(zend_execute_internal == NULL)) {
854			/* saves one function call if zend_execute_internal is not used */
855			func->internal_function.handler(call, fci->retval);
856		} else {
857			zend_execute_internal(call, fci->retval);
858		}
859		EG(current_execute_data) = call->prev_execute_data;
860		zend_vm_stack_free_args(call);
861
862		/*  We shouldn't fix bad extensions here,
863			because it can break proper ones (Bug #34045)
864		if (!EX(function_state).function->common.return_reference)
865		{
866			INIT_PZVAL(f->retval);
867		}*/
868		if (EG(exception)) {
869			zval_ptr_dtor(fci->retval);
870			ZVAL_UNDEF(fci->retval);
871		}
872
873		if (call_via_handler) {
874			/* We must re-initialize function again */
875			fci_cache->initialized = 0;
876		}
877	} else { /* ZEND_OVERLOADED_FUNCTION */
878		ZVAL_NULL(fci->retval);
879
880		/* Not sure what should be done here if it's a static method */
881		if (fci->object) {
882			call->prev_execute_data = EG(current_execute_data);
883			EG(current_execute_data) = call;
884			fci->object->handlers->call_method(func->common.function_name, fci->object, call, fci->retval);
885			EG(current_execute_data) = call->prev_execute_data;
886		} else {
887			zend_throw_error(NULL, "Cannot call overloaded function for non-object");
888		}
889
890		zend_vm_stack_free_args(call);
891
892		if (func->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
893			zend_string_release(func->common.function_name);
894		}
895		efree(func);
896
897		if (EG(exception)) {
898			zval_ptr_dtor(fci->retval);
899			ZVAL_UNDEF(fci->retval);
900		}
901	}
902
903	zend_vm_stack_free_call_frame(call);
904
905	if (EG(current_execute_data) == &dummy_execute_data) {
906		EG(current_execute_data) = dummy_execute_data.prev_execute_data;
907	}
908
909	if (EG(exception)) {
910		zend_throw_exception_internal(NULL);
911	}
912	return SUCCESS;
913}
914/* }}} */
915
916ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, const zval *key, int use_autoload) /* {{{ */
917{
918	zend_class_entry *ce = NULL;
919	zval args[1];
920	zval local_retval;
921	zend_string *lc_name;
922	zend_fcall_info fcall_info;
923	zend_fcall_info_cache fcall_cache;
924
925	if (key) {
926		lc_name = Z_STR_P(key);
927	} else {
928		if (name == NULL || !ZSTR_LEN(name)) {
929			return NULL;
930		}
931
932		if (ZSTR_VAL(name)[0] == '\\') {
933			lc_name = zend_string_alloc(ZSTR_LEN(name) - 1, 0);
934			zend_str_tolower_copy(ZSTR_VAL(lc_name), ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1);
935		} else {
936			lc_name = zend_string_tolower(name);
937		}
938	}
939
940	ce = zend_hash_find_ptr(EG(class_table), lc_name);
941	if (ce) {
942		if (!key) {
943			zend_string_release(lc_name);
944		}
945		return ce;
946	}
947
948	/* The compiler is not-reentrant. Make sure we __autoload() only during run-time
949	 * (doesn't impact functionality of __autoload()
950	*/
951	if (!use_autoload || zend_is_compiling()) {
952		if (!key) {
953			zend_string_release(lc_name);
954		}
955		return NULL;
956	}
957
958	if (!EG(autoload_func)) {
959		zend_function *func = zend_hash_str_find_ptr(EG(function_table), ZEND_AUTOLOAD_FUNC_NAME, sizeof(ZEND_AUTOLOAD_FUNC_NAME) - 1);
960		if (func) {
961			EG(autoload_func) = func;
962		} else {
963			if (!key) {
964				zend_string_release(lc_name);
965			}
966			return NULL;
967		}
968
969	}
970
971	/* Verify class name before passing it to __autoload() */
972	if (strspn(ZSTR_VAL(name), "0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\177\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)) {
973		if (!key) {
974			zend_string_release(lc_name);
975		}
976		return NULL;
977	}
978
979	if (EG(in_autoload) == NULL) {
980		ALLOC_HASHTABLE(EG(in_autoload));
981		zend_hash_init(EG(in_autoload), 8, NULL, NULL, 0);
982	}
983
984	if (zend_hash_add_empty_element(EG(in_autoload), lc_name) == NULL) {
985		if (!key) {
986			zend_string_release(lc_name);
987		}
988		return NULL;
989	}
990
991	ZVAL_UNDEF(&local_retval);
992
993	if (ZSTR_VAL(name)[0] == '\\') {
994		ZVAL_STRINGL(&args[0], ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1);
995	} else {
996		ZVAL_STR_COPY(&args[0], name);
997	}
998
999	fcall_info.size = sizeof(fcall_info);
1000	ZVAL_STR_COPY(&fcall_info.function_name, EG(autoload_func)->common.function_name);
1001	fcall_info.retval = &local_retval;
1002	fcall_info.param_count = 1;
1003	fcall_info.params = args;
1004	fcall_info.object = NULL;
1005	fcall_info.no_separation = 1;
1006
1007	fcall_cache.initialized = 1;
1008	fcall_cache.function_handler = EG(autoload_func);
1009	fcall_cache.calling_scope = NULL;
1010	fcall_cache.called_scope = NULL;
1011	fcall_cache.object = NULL;
1012
1013	zend_exception_save();
1014	if ((zend_call_function(&fcall_info, &fcall_cache) == SUCCESS) && !EG(exception)) {
1015		ce = zend_hash_find_ptr(EG(class_table), lc_name);
1016	}
1017	zend_exception_restore();
1018
1019	zval_ptr_dtor(&args[0]);
1020	zval_dtor(&fcall_info.function_name);
1021
1022	zend_hash_del(EG(in_autoload), lc_name);
1023
1024	zval_ptr_dtor(&local_retval);
1025
1026	if (!key) {
1027		zend_string_release(lc_name);
1028	}
1029	return ce;
1030}
1031/* }}} */
1032
1033ZEND_API zend_class_entry *zend_lookup_class(zend_string *name) /* {{{ */
1034{
1035	return zend_lookup_class_ex(name, NULL, 1);
1036}
1037/* }}} */
1038
1039ZEND_API zend_class_entry *zend_get_called_scope(zend_execute_data *ex) /* {{{ */
1040{
1041	while (ex) {
1042		if (Z_TYPE(ex->This) == IS_OBJECT) {
1043			return Z_OBJCE(ex->This);
1044		} else if (Z_CE(ex->This)) {
1045			return Z_CE(ex->This);
1046		} else if (ex->func) {
1047			if (ex->func->type != ZEND_INTERNAL_FUNCTION || ex->func->common.scope) {
1048				return NULL;
1049			}
1050		}
1051		ex = ex->prev_execute_data;
1052	}
1053	return NULL;
1054}
1055/* }}} */
1056
1057ZEND_API zend_object *zend_get_this_object(zend_execute_data *ex) /* {{{ */
1058{
1059	while (ex) {
1060		if (Z_TYPE(ex->This) == IS_OBJECT) {
1061			return Z_OBJ(ex->This);
1062		} else if (ex->func) {
1063			if (ex->func->type != ZEND_INTERNAL_FUNCTION || ex->func->common.scope) {
1064				return NULL;
1065			}
1066		}
1067		ex = ex->prev_execute_data;
1068	}
1069	return NULL;
1070}
1071/* }}} */
1072
1073ZEND_API int zend_eval_stringl(char *str, size_t str_len, zval *retval_ptr, char *string_name) /* {{{ */
1074{
1075	zval pv;
1076	zend_op_array *new_op_array;
1077	uint32_t original_compiler_options;
1078	int retval;
1079
1080	if (retval_ptr) {
1081		ZVAL_NEW_STR(&pv, zend_string_alloc(str_len + sizeof("return ;")-1, 1));
1082		memcpy(Z_STRVAL(pv), "return ", sizeof("return ") - 1);
1083		memcpy(Z_STRVAL(pv) + sizeof("return ") - 1, str, str_len);
1084		Z_STRVAL(pv)[Z_STRLEN(pv) - 1] = ';';
1085		Z_STRVAL(pv)[Z_STRLEN(pv)] = '\0';
1086	} else {
1087		ZVAL_STRINGL(&pv, str, str_len);
1088	}
1089
1090	/*printf("Evaluating '%s'\n", pv.value.str.val);*/
1091
1092	original_compiler_options = CG(compiler_options);
1093	CG(compiler_options) = ZEND_COMPILE_DEFAULT_FOR_EVAL;
1094	new_op_array = zend_compile_string(&pv, string_name);
1095	CG(compiler_options) = original_compiler_options;
1096
1097	if (new_op_array) {
1098		zval local_retval;
1099
1100		EG(no_extensions)=1;
1101
1102		zend_try {
1103			ZVAL_UNDEF(&local_retval);
1104			zend_execute(new_op_array, &local_retval);
1105		} zend_catch {
1106			destroy_op_array(new_op_array);
1107			efree_size(new_op_array, sizeof(zend_op_array));
1108			zend_bailout();
1109		} zend_end_try();
1110
1111		if (Z_TYPE(local_retval) != IS_UNDEF) {
1112			if (retval_ptr) {
1113				ZVAL_COPY_VALUE(retval_ptr, &local_retval);
1114			} else {
1115				zval_ptr_dtor(&local_retval);
1116			}
1117		} else {
1118			if (retval_ptr) {
1119				ZVAL_NULL(retval_ptr);
1120			}
1121		}
1122
1123		EG(no_extensions)=0;
1124		destroy_op_array(new_op_array);
1125		efree_size(new_op_array, sizeof(zend_op_array));
1126		retval = SUCCESS;
1127	} else {
1128		retval = FAILURE;
1129	}
1130	zval_dtor(&pv);
1131	return retval;
1132}
1133/* }}} */
1134
1135ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name) /* {{{ */
1136{
1137	return zend_eval_stringl(str, strlen(str), retval_ptr, string_name);
1138}
1139/* }}} */
1140
1141ZEND_API int zend_eval_stringl_ex(char *str, size_t str_len, zval *retval_ptr, char *string_name, int handle_exceptions) /* {{{ */
1142{
1143	int result;
1144
1145	result = zend_eval_stringl(str, str_len, retval_ptr, string_name);
1146	if (handle_exceptions && EG(exception)) {
1147		zend_exception_error(EG(exception), E_ERROR);
1148		result = FAILURE;
1149	}
1150	return result;
1151}
1152/* }}} */
1153
1154ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name, int handle_exceptions) /* {{{ */
1155{
1156	return zend_eval_stringl_ex(str, strlen(str), retval_ptr, string_name, handle_exceptions);
1157}
1158/* }}} */
1159
1160static void zend_set_timeout_ex(zend_long seconds, int reset_signals);
1161
1162ZEND_API ZEND_NORETURN void zend_timeout(int dummy) /* {{{ */
1163{
1164	EG(timed_out) = 0;
1165	zend_set_timeout_ex(0, 1);
1166	zend_error_noreturn(E_ERROR, "Maximum execution time of %pd second%s exceeded", EG(timeout_seconds), EG(timeout_seconds) == 1 ? "" : "s");
1167}
1168/* }}} */
1169
1170#ifndef ZEND_WIN32
1171static void zend_timeout_handler(int dummy) /* {{{ */
1172{
1173#ifndef ZTS
1174    if (EG(timed_out)) {
1175		/* Die on hard timeout */
1176		const char *error_filename = NULL;
1177		uint error_lineno = 0;
1178		char *log_buffer = NULL;
1179
1180		if (zend_is_compiling()) {
1181			error_filename = ZSTR_VAL(zend_get_compiled_filename());
1182			error_lineno = zend_get_compiled_lineno();
1183		} else if (zend_is_executing()) {
1184			error_filename = zend_get_executed_filename();
1185			if (error_filename[0] == '[') { /* [no active file] */
1186				error_filename = NULL;
1187				error_lineno = 0;
1188			} else {
1189				error_lineno = zend_get_executed_lineno();
1190			}
1191		}
1192		if (!error_filename) {
1193			error_filename = "Unknown";
1194		}
1195
1196		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);
1197		write(2, log_buffer, strlen(log_buffer));
1198		_exit(1);
1199    }
1200#endif
1201
1202	if (zend_on_timeout) {
1203#ifdef ZEND_SIGNALS
1204		/*
1205		   We got here because we got a timeout signal, so we are in a signal handler
1206		   at this point. However, we want to be able to timeout any user-supplied
1207		   shutdown functions, so pretend we are not in a signal handler while we are
1208		   calling these
1209		*/
1210		SIGG(running) = 0;
1211#endif
1212		zend_on_timeout(EG(timeout_seconds));
1213	}
1214
1215	EG(timed_out) = 1;
1216
1217#ifndef ZTS
1218	if (EG(hard_timeout) > 0) {
1219		/* Set hard timeout */
1220		zend_set_timeout_ex(EG(hard_timeout), 1);
1221	}
1222#endif
1223}
1224/* }}} */
1225#endif
1226
1227#ifdef ZEND_WIN32
1228VOID CALLBACK tq_timer_cb(PVOID arg, BOOLEAN timed_out)
1229{
1230	zend_bool *php_timed_out;
1231
1232	/* The doc states it'll be always true, however it theoretically
1233		could be FALSE when the thread was signaled. */
1234	if (!timed_out) {
1235		return;
1236	}
1237
1238	php_timed_out = (zend_bool *)arg;
1239	*php_timed_out = 1;
1240}
1241#endif
1242
1243/* This one doesn't exists on QNX */
1244#ifndef SIGPROF
1245#define SIGPROF 27
1246#endif
1247
1248static void zend_set_timeout_ex(zend_long seconds, int reset_signals) /* {{{ */
1249{
1250
1251#ifdef ZEND_WIN32
1252	if(!seconds) {
1253		return;
1254	}
1255
1256        /* Don't use ChangeTimerQueueTimer() as it will not restart an expired
1257		timer, so we could end up with just an ignored timeout. Instead
1258		delete and recreate. */
1259	if (NULL != tq_timer) {
1260		if (!DeleteTimerQueueTimer(NULL, tq_timer, NULL)) {
1261			tq_timer = NULL;
1262			zend_error_noreturn(E_ERROR, "Could not delete queued timer");
1263			return;
1264		}
1265		tq_timer = NULL;
1266	}
1267
1268	/* XXX passing NULL means the default timer queue provided by the system is used */
1269	if (!CreateTimerQueueTimer(&tq_timer, NULL, (WAITORTIMERCALLBACK)tq_timer_cb, (VOID*)&EG(timed_out), seconds*1000, 0, WT_EXECUTEONLYONCE)) {
1270		tq_timer = NULL;
1271		zend_error_noreturn(E_ERROR, "Could not queue new timer");
1272		return;
1273	}
1274#else
1275#	ifdef HAVE_SETITIMER
1276	{
1277		struct itimerval t_r;		/* timeout requested */
1278		int signo;
1279
1280		if(seconds) {
1281			t_r.it_value.tv_sec = seconds;
1282			t_r.it_value.tv_usec = t_r.it_interval.tv_sec = t_r.it_interval.tv_usec = 0;
1283
1284#	ifdef __CYGWIN__
1285			setitimer(ITIMER_REAL, &t_r, NULL);
1286		}
1287		signo = SIGALRM;
1288#	else
1289			setitimer(ITIMER_PROF, &t_r, NULL);
1290		}
1291		signo = SIGPROF;
1292#	endif
1293
1294		if (reset_signals) {
1295#	ifdef ZEND_SIGNALS
1296			zend_signal(signo, zend_timeout_handler);
1297#	else
1298			sigset_t sigset;
1299#   ifdef HAVE_SIGACTION
1300			struct sigaction act;
1301
1302			act.sa_handler = zend_timeout_handler;
1303			sigemptyset(&act.sa_mask);
1304			act.sa_flags = SA_RESETHAND | SA_NODEFER;
1305			sigaction(signo, &act, NULL);
1306#   else
1307			signal(signo, zend_timeout_handler);
1308#   endif /* HAVE_SIGACTION */
1309			sigemptyset(&sigset);
1310			sigaddset(&sigset, signo);
1311			sigprocmask(SIG_UNBLOCK, &sigset, NULL);
1312#	endif /* ZEND_SIGNALS */
1313		}
1314	}
1315#	endif /* HAVE_SETITIMER */
1316#endif
1317}
1318/* }}} */
1319
1320void zend_set_timeout(zend_long seconds, int reset_signals) /* {{{ */
1321{
1322
1323	EG(timeout_seconds) = seconds;
1324	zend_set_timeout_ex(seconds, reset_signals);
1325	EG(timed_out) = 0;
1326}
1327/* }}} */
1328
1329void zend_unset_timeout(void) /* {{{ */
1330{
1331#ifdef ZEND_WIN32
1332	if (NULL != tq_timer) {
1333		if (!DeleteTimerQueueTimer(NULL, tq_timer, NULL)) {
1334			EG(timed_out) = 0;
1335			tq_timer = NULL;
1336			zend_error_noreturn(E_ERROR, "Could not delete queued timer");
1337			return;
1338		}
1339		tq_timer = NULL;
1340	}
1341	EG(timed_out) = 0;
1342#else
1343#	ifdef HAVE_SETITIMER
1344	if (EG(timeout_seconds)) {
1345		struct itimerval no_timeout;
1346
1347		no_timeout.it_value.tv_sec = no_timeout.it_value.tv_usec = no_timeout.it_interval.tv_sec = no_timeout.it_interval.tv_usec = 0;
1348
1349#ifdef __CYGWIN__
1350		setitimer(ITIMER_REAL, &no_timeout, NULL);
1351#else
1352		setitimer(ITIMER_PROF, &no_timeout, NULL);
1353#endif
1354	}
1355#	endif
1356	EG(timed_out) = 0;
1357#endif
1358}
1359/* }}} */
1360
1361zend_class_entry *zend_fetch_class(zend_string *class_name, int fetch_type) /* {{{ */
1362{
1363	zend_class_entry *ce, *scope;
1364	int fetch_sub_type = fetch_type & ZEND_FETCH_CLASS_MASK;
1365
1366check_fetch_type:
1367	switch (fetch_sub_type) {
1368		case ZEND_FETCH_CLASS_SELF:
1369			scope = zend_get_executed_scope();
1370			if (UNEXPECTED(!scope)) {
1371				zend_throw_or_error(fetch_type, NULL, "Cannot access self:: when no class scope is active");
1372			}
1373			return scope;
1374		case ZEND_FETCH_CLASS_PARENT:
1375			scope = zend_get_executed_scope();
1376			if (UNEXPECTED(!scope)) {
1377				zend_throw_or_error(fetch_type, NULL, "Cannot access parent:: when no class scope is active");
1378				return NULL;
1379			}
1380			if (UNEXPECTED(!scope->parent)) {
1381				zend_throw_or_error(fetch_type, NULL, "Cannot access parent:: when current class scope has no parent");
1382			}
1383			return scope->parent;
1384		case ZEND_FETCH_CLASS_STATIC:
1385			ce = zend_get_called_scope(EG(current_execute_data));
1386			if (UNEXPECTED(!ce)) {
1387				zend_throw_or_error(fetch_type, NULL, "Cannot access static:: when no class scope is active");
1388				return NULL;
1389			}
1390			return ce;
1391		case ZEND_FETCH_CLASS_AUTO: {
1392				fetch_sub_type = zend_get_class_fetch_type(class_name);
1393				if (UNEXPECTED(fetch_sub_type != ZEND_FETCH_CLASS_DEFAULT)) {
1394					goto check_fetch_type;
1395				}
1396			}
1397			break;
1398	}
1399
1400	if (fetch_type & ZEND_FETCH_CLASS_NO_AUTOLOAD) {
1401		return zend_lookup_class_ex(class_name, NULL, 0);
1402	} else if ((ce = zend_lookup_class_ex(class_name, NULL, 1)) == NULL) {
1403		if (!(fetch_type & ZEND_FETCH_CLASS_SILENT) && !EG(exception)) {
1404			if (fetch_sub_type == ZEND_FETCH_CLASS_INTERFACE) {
1405				zend_throw_or_error(fetch_type, NULL, "Interface '%s' not found", ZSTR_VAL(class_name));
1406			} else if (fetch_sub_type == ZEND_FETCH_CLASS_TRAIT) {
1407				zend_throw_or_error(fetch_type, NULL, "Trait '%s' not found", ZSTR_VAL(class_name));
1408			} else {
1409				zend_throw_or_error(fetch_type, NULL, "Class '%s' not found", ZSTR_VAL(class_name));
1410			}
1411		}
1412		return NULL;
1413	}
1414	return ce;
1415}
1416/* }}} */
1417
1418zend_class_entry *zend_fetch_class_by_name(zend_string *class_name, const zval *key, int fetch_type) /* {{{ */
1419{
1420	zend_class_entry *ce;
1421
1422	if (fetch_type & ZEND_FETCH_CLASS_NO_AUTOLOAD) {
1423		return zend_lookup_class_ex(class_name, key, 0);
1424	} else if ((ce = zend_lookup_class_ex(class_name, key, 1)) == NULL) {
1425		if ((fetch_type & ZEND_FETCH_CLASS_SILENT) == 0 && !EG(exception)) {
1426			if ((fetch_type & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_INTERFACE) {
1427				zend_throw_or_error(fetch_type, NULL, "Interface '%s' not found", ZSTR_VAL(class_name));
1428			} else if ((fetch_type & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_TRAIT) {
1429				zend_throw_or_error(fetch_type, NULL, "Trait '%s' not found", ZSTR_VAL(class_name));
1430			} else {
1431				zend_throw_or_error(fetch_type, NULL, "Class '%s' not found", ZSTR_VAL(class_name));
1432			}
1433		}
1434		return NULL;
1435	}
1436	return ce;
1437}
1438/* }}} */
1439
1440#define MAX_ABSTRACT_INFO_CNT 3
1441#define MAX_ABSTRACT_INFO_FMT "%s%s%s%s"
1442#define DISPLAY_ABSTRACT_FN(idx) \
1443	ai.afn[idx] ? ZEND_FN_SCOPE_NAME(ai.afn[idx]) : "", \
1444	ai.afn[idx] ? "::" : "", \
1445	ai.afn[idx] ? ZSTR_VAL(ai.afn[idx]->common.function_name) : "", \
1446	ai.afn[idx] && ai.afn[idx + 1] ? ", " : (ai.afn[idx] && ai.cnt > MAX_ABSTRACT_INFO_CNT ? ", ..." : "")
1447
1448typedef struct _zend_abstract_info {
1449	zend_function *afn[MAX_ABSTRACT_INFO_CNT + 1];
1450	int cnt;
1451	int ctor;
1452} zend_abstract_info;
1453
1454static void zend_verify_abstract_class_function(zend_function *fn, zend_abstract_info *ai) /* {{{ */
1455{
1456	if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
1457		if (ai->cnt < MAX_ABSTRACT_INFO_CNT) {
1458			ai->afn[ai->cnt] = fn;
1459		}
1460		if (fn->common.fn_flags & ZEND_ACC_CTOR) {
1461			if (!ai->ctor) {
1462				ai->cnt++;
1463				ai->ctor = 1;
1464			} else {
1465				ai->afn[ai->cnt] = NULL;
1466			}
1467		} else {
1468			ai->cnt++;
1469		}
1470	}
1471}
1472/* }}} */
1473
1474void zend_verify_abstract_class(zend_class_entry *ce) /* {{{ */
1475{
1476	zend_function *func;
1477	zend_abstract_info ai;
1478
1479	if ((ce->ce_flags & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS) && !(ce->ce_flags & (ZEND_ACC_TRAIT | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS))) {
1480		memset(&ai, 0, sizeof(ai));
1481
1482		ZEND_HASH_FOREACH_PTR(&ce->function_table, func) {
1483			zend_verify_abstract_class_function(func, &ai);
1484		} ZEND_HASH_FOREACH_END();
1485
1486		if (ai.cnt) {
1487			zend_error_noreturn(E_ERROR, "Class %s contains %d abstract method%s and must therefore be declared abstract or implement the remaining methods (" MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT ")",
1488				ZSTR_VAL(ce->name), ai.cnt,
1489				ai.cnt > 1 ? "s" : "",
1490				DISPLAY_ABSTRACT_FN(0),
1491				DISPLAY_ABSTRACT_FN(1),
1492				DISPLAY_ABSTRACT_FN(2)
1493				);
1494		}
1495	}
1496}
1497/* }}} */
1498
1499ZEND_API int zend_delete_global_variable(zend_string *name) /* {{{ */
1500{
1501    return zend_hash_del_ind(&EG(symbol_table), name);
1502}
1503/* }}} */
1504
1505ZEND_API zend_array *zend_rebuild_symbol_table(void) /* {{{ */
1506{
1507	zend_execute_data *ex;
1508	zend_array *symbol_table;
1509
1510	/* Search for last called user function */
1511	ex = EG(current_execute_data);
1512	while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->common.type))) {
1513		ex = ex->prev_execute_data;
1514	}
1515	if (!ex) {
1516		return NULL;
1517	}
1518	if (ZEND_CALL_INFO(ex) & ZEND_CALL_HAS_SYMBOL_TABLE) {
1519		return ex->symbol_table;
1520	}
1521
1522	ZEND_ADD_CALL_FLAG(ex, ZEND_CALL_HAS_SYMBOL_TABLE);
1523	if (EG(symtable_cache_ptr) >= EG(symtable_cache)) {
1524		/*printf("Cache hit!  Reusing %x\n", symtable_cache[symtable_cache_ptr]);*/
1525		symbol_table = ex->symbol_table = *(EG(symtable_cache_ptr)--);
1526		if (!ex->func->op_array.last_var) {
1527			return symbol_table;
1528		}
1529		zend_hash_extend(symbol_table, ex->func->op_array.last_var, 0);
1530	} else {
1531		symbol_table = ex->symbol_table = emalloc(sizeof(zend_array));
1532		zend_hash_init(symbol_table, ex->func->op_array.last_var, NULL, ZVAL_PTR_DTOR, 0);
1533		if (!ex->func->op_array.last_var) {
1534			return symbol_table;
1535		}
1536		zend_hash_real_init(symbol_table, 0);
1537		/*printf("Cache miss!  Initialized %x\n", EG(active_symbol_table));*/
1538	}
1539	if (EXPECTED(ex->func->op_array.last_var)) {
1540		zend_string **str = ex->func->op_array.vars;
1541		zend_string **end = str + ex->func->op_array.last_var;
1542		zval *var = ZEND_CALL_VAR_NUM(ex, 0);
1543
1544		do {
1545			_zend_hash_append_ind(symbol_table, *str, var);
1546			str++;
1547			var++;
1548		} while (str != end);
1549	}
1550	return symbol_table;
1551}
1552/* }}} */
1553
1554ZEND_API void zend_attach_symbol_table(zend_execute_data *execute_data) /* {{{ */
1555{
1556	zend_op_array *op_array = &execute_data->func->op_array;
1557	HashTable *ht = execute_data->symbol_table;
1558
1559	/* copy real values from symbol table into CV slots and create
1560	   INDIRECT references to CV in symbol table  */
1561	if (EXPECTED(op_array->last_var)) {
1562		zend_string **str = op_array->vars;
1563		zend_string **end = str + op_array->last_var;
1564		zval *var = EX_VAR_NUM(0);
1565
1566		do {
1567			zval *zv = zend_hash_find(ht, *str);
1568
1569			if (zv) {
1570				if (Z_TYPE_P(zv) == IS_INDIRECT) {
1571					zval *val = Z_INDIRECT_P(zv);
1572
1573					ZVAL_COPY_VALUE(var, val);
1574				} else {
1575					ZVAL_COPY_VALUE(var, zv);
1576				}
1577			} else {
1578				ZVAL_UNDEF(var);
1579				zv = zend_hash_add_new(ht, *str, var);
1580			}
1581			ZVAL_INDIRECT(zv, var);
1582			str++;
1583			var++;
1584		} while (str != end);
1585	}
1586}
1587/* }}} */
1588
1589ZEND_API void zend_detach_symbol_table(zend_execute_data *execute_data) /* {{{ */
1590{
1591	zend_op_array *op_array = &execute_data->func->op_array;
1592	HashTable *ht = execute_data->symbol_table;
1593
1594	/* copy real values from CV slots into symbol table */
1595	if (EXPECTED(op_array->last_var)) {
1596		zend_string **str = op_array->vars;
1597		zend_string **end = str + op_array->last_var;
1598		zval *var = EX_VAR_NUM(0);
1599
1600		do {
1601			if (Z_TYPE_P(var) == IS_UNDEF) {
1602				zend_hash_del(ht, *str);
1603			} else {
1604				zend_hash_update(ht, *str, var);
1605				ZVAL_UNDEF(var);
1606			}
1607			str++;
1608			var++;
1609		} while (str != end);
1610	}
1611}
1612/* }}} */
1613
1614ZEND_API int zend_set_local_var(zend_string *name, zval *value, int force) /* {{{ */
1615{
1616	zend_execute_data *execute_data = EG(current_execute_data);
1617
1618	while (execute_data && (!execute_data->func || !ZEND_USER_CODE(execute_data->func->common.type))) {
1619		execute_data = execute_data->prev_execute_data;
1620	}
1621
1622	if (execute_data) {
1623		if (!(EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE)) {
1624			zend_ulong h = zend_string_hash_val(name);
1625			zend_op_array *op_array = &execute_data->func->op_array;
1626
1627			if (EXPECTED(op_array->last_var)) {
1628				zend_string **str = op_array->vars;
1629				zend_string **end = str + op_array->last_var;
1630
1631				do {
1632					if (ZSTR_H(*str) == h &&
1633					    ZSTR_LEN(*str) == ZSTR_LEN(name) &&
1634					    memcmp(ZSTR_VAL(*str), ZSTR_VAL(name), ZSTR_LEN(name)) == 0) {
1635						zval *var = EX_VAR_NUM(str - op_array->vars);
1636						ZVAL_COPY_VALUE(var, value);
1637						return SUCCESS;
1638					}
1639					str++;
1640				} while (str != end);
1641			}
1642			if (force) {
1643				zend_array *symbol_table = zend_rebuild_symbol_table();
1644				if (symbol_table) {
1645					return zend_hash_update(symbol_table, name, value) ? SUCCESS : FAILURE;;
1646				}
1647			}
1648		} else {
1649			return (zend_hash_update_ind(execute_data->symbol_table, name, value) != NULL) ? SUCCESS : FAILURE;
1650		}
1651	}
1652	return FAILURE;
1653}
1654/* }}} */
1655
1656ZEND_API int zend_set_local_var_str(const char *name, size_t len, zval *value, int force) /* {{{ */
1657{
1658	zend_execute_data *execute_data = EG(current_execute_data);
1659
1660	while (execute_data && (!execute_data->func || !ZEND_USER_CODE(execute_data->func->common.type))) {
1661		execute_data = execute_data->prev_execute_data;
1662	}
1663
1664	if (execute_data) {
1665		if (!(EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE)) {
1666			zend_ulong h = zend_hash_func(name, len);
1667			zend_op_array *op_array = &execute_data->func->op_array;
1668			if (EXPECTED(op_array->last_var)) {
1669				zend_string **str = op_array->vars;
1670				zend_string **end = str + op_array->last_var;
1671
1672				do {
1673					if (ZSTR_H(*str) == h &&
1674					    ZSTR_LEN(*str) == len &&
1675					    memcmp(ZSTR_VAL(*str), name, len) == 0) {
1676						zval *var = EX_VAR_NUM(str - op_array->vars);
1677						zval_ptr_dtor(var);
1678						ZVAL_COPY_VALUE(var, value);
1679						return SUCCESS;
1680					}
1681					str++;
1682				} while (str != end);
1683			}
1684			if (force) {
1685				zend_array *symbol_table = zend_rebuild_symbol_table();
1686				if (symbol_table) {
1687					return zend_hash_str_update(symbol_table, name, len, value) ? SUCCESS : FAILURE;;
1688				}
1689			}
1690		} else {
1691			return (zend_hash_str_update_ind(execute_data->symbol_table, name, len, value) != NULL) ? SUCCESS : FAILURE;
1692		}
1693	}
1694	return FAILURE;
1695}
1696/* }}} */
1697
1698/*
1699 * Local variables:
1700 * tab-width: 4
1701 * c-basic-offset: 4
1702 * indent-tabs-mode: t
1703 * End:
1704 */
1705