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 | ZEND_CALL_DYNAMIC,
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		zend_init_execute_data(call, &func->op_array, fci->retval);
838		zend_execute_ex(call);
839		if (call_via_handler) {
840			/* We must re-initialize function again */
841			fci_cache->initialized = 0;
842		}
843	} else if (func->type == ZEND_INTERNAL_FUNCTION) {
844		int call_via_handler = (func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) != 0;
845		ZVAL_NULL(fci->retval);
846		call->prev_execute_data = EG(current_execute_data);
847		call->return_value = NULL; /* this is not a constructor call */
848		EG(current_execute_data) = call;
849		if (EXPECTED(zend_execute_internal == NULL)) {
850			/* saves one function call if zend_execute_internal is not used */
851			func->internal_function.handler(call, fci->retval);
852		} else {
853			zend_execute_internal(call, fci->retval);
854		}
855		EG(current_execute_data) = call->prev_execute_data;
856		zend_vm_stack_free_args(call);
857
858		/*  We shouldn't fix bad extensions here,
859			because it can break proper ones (Bug #34045)
860		if (!EX(function_state).function->common.return_reference)
861		{
862			INIT_PZVAL(f->retval);
863		}*/
864		if (EG(exception)) {
865			zval_ptr_dtor(fci->retval);
866			ZVAL_UNDEF(fci->retval);
867		}
868
869		if (call_via_handler) {
870			/* We must re-initialize function again */
871			fci_cache->initialized = 0;
872		}
873	} else { /* ZEND_OVERLOADED_FUNCTION */
874		ZVAL_NULL(fci->retval);
875
876		/* Not sure what should be done here if it's a static method */
877		if (fci->object) {
878			call->prev_execute_data = EG(current_execute_data);
879			EG(current_execute_data) = call;
880			fci->object->handlers->call_method(func->common.function_name, fci->object, call, fci->retval);
881			EG(current_execute_data) = call->prev_execute_data;
882		} else {
883			zend_throw_error(NULL, "Cannot call overloaded function for non-object");
884		}
885
886		zend_vm_stack_free_args(call);
887
888		if (func->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
889			zend_string_release(func->common.function_name);
890		}
891		efree(func);
892
893		if (EG(exception)) {
894			zval_ptr_dtor(fci->retval);
895			ZVAL_UNDEF(fci->retval);
896		}
897	}
898
899	zend_vm_stack_free_call_frame(call);
900
901	if (EG(current_execute_data) == &dummy_execute_data) {
902		EG(current_execute_data) = dummy_execute_data.prev_execute_data;
903	}
904
905	if (EG(exception)) {
906		zend_throw_exception_internal(NULL);
907	}
908	return SUCCESS;
909}
910/* }}} */
911
912ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, const zval *key, int use_autoload) /* {{{ */
913{
914	zend_class_entry *ce = NULL;
915	zval args[1];
916	zval local_retval;
917	zend_string *lc_name;
918	zend_fcall_info fcall_info;
919	zend_fcall_info_cache fcall_cache;
920
921	if (key) {
922		lc_name = Z_STR_P(key);
923	} else {
924		if (name == NULL || !ZSTR_LEN(name)) {
925			return NULL;
926		}
927
928		if (ZSTR_VAL(name)[0] == '\\') {
929			lc_name = zend_string_alloc(ZSTR_LEN(name) - 1, 0);
930			zend_str_tolower_copy(ZSTR_VAL(lc_name), ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1);
931		} else {
932			lc_name = zend_string_tolower(name);
933		}
934	}
935
936	ce = zend_hash_find_ptr(EG(class_table), lc_name);
937	if (ce) {
938		if (!key) {
939			zend_string_release(lc_name);
940		}
941		return ce;
942	}
943
944	/* The compiler is not-reentrant. Make sure we __autoload() only during run-time
945	 * (doesn't impact functionality of __autoload()
946	*/
947	if (!use_autoload || zend_is_compiling()) {
948		if (!key) {
949			zend_string_release(lc_name);
950		}
951		return NULL;
952	}
953
954	if (!EG(autoload_func)) {
955		zend_function *func = zend_hash_find_ptr(EG(function_table), CG(known_strings)[ZEND_STR_MAGIC_AUTOLOAD]);
956		if (func) {
957			EG(autoload_func) = func;
958		} else {
959			if (!key) {
960				zend_string_release(lc_name);
961			}
962			return NULL;
963		}
964
965	}
966
967	/* Verify class name before passing it to __autoload() */
968	if (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)) {
969		if (!key) {
970			zend_string_release(lc_name);
971		}
972		return NULL;
973	}
974
975	if (EG(in_autoload) == NULL) {
976		ALLOC_HASHTABLE(EG(in_autoload));
977		zend_hash_init(EG(in_autoload), 8, NULL, NULL, 0);
978	}
979
980	if (zend_hash_add_empty_element(EG(in_autoload), lc_name) == NULL) {
981		if (!key) {
982			zend_string_release(lc_name);
983		}
984		return NULL;
985	}
986
987	ZVAL_UNDEF(&local_retval);
988
989	if (ZSTR_VAL(name)[0] == '\\') {
990		ZVAL_STRINGL(&args[0], ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1);
991	} else {
992		ZVAL_STR_COPY(&args[0], name);
993	}
994
995	fcall_info.size = sizeof(fcall_info);
996	ZVAL_STR_COPY(&fcall_info.function_name, EG(autoload_func)->common.function_name);
997	fcall_info.retval = &local_retval;
998	fcall_info.param_count = 1;
999	fcall_info.params = args;
1000	fcall_info.object = NULL;
1001	fcall_info.no_separation = 1;
1002
1003	fcall_cache.initialized = 1;
1004	fcall_cache.function_handler = EG(autoload_func);
1005	fcall_cache.calling_scope = NULL;
1006	fcall_cache.called_scope = NULL;
1007	fcall_cache.object = NULL;
1008
1009	zend_exception_save();
1010	if ((zend_call_function(&fcall_info, &fcall_cache) == SUCCESS) && !EG(exception)) {
1011		ce = zend_hash_find_ptr(EG(class_table), lc_name);
1012	}
1013	zend_exception_restore();
1014
1015	zval_ptr_dtor(&args[0]);
1016	zval_dtor(&fcall_info.function_name);
1017
1018	zend_hash_del(EG(in_autoload), lc_name);
1019
1020	zval_ptr_dtor(&local_retval);
1021
1022	if (!key) {
1023		zend_string_release(lc_name);
1024	}
1025	return ce;
1026}
1027/* }}} */
1028
1029ZEND_API zend_class_entry *zend_lookup_class(zend_string *name) /* {{{ */
1030{
1031	return zend_lookup_class_ex(name, NULL, 1);
1032}
1033/* }}} */
1034
1035ZEND_API zend_class_entry *zend_get_called_scope(zend_execute_data *ex) /* {{{ */
1036{
1037	while (ex) {
1038		if (Z_TYPE(ex->This) == IS_OBJECT) {
1039			return Z_OBJCE(ex->This);
1040		} else if (Z_CE(ex->This)) {
1041			return Z_CE(ex->This);
1042		} else if (ex->func) {
1043			if (ex->func->type != ZEND_INTERNAL_FUNCTION || ex->func->common.scope) {
1044				return NULL;
1045			}
1046		}
1047		ex = ex->prev_execute_data;
1048	}
1049	return NULL;
1050}
1051/* }}} */
1052
1053ZEND_API zend_object *zend_get_this_object(zend_execute_data *ex) /* {{{ */
1054{
1055	while (ex) {
1056		if (Z_TYPE(ex->This) == IS_OBJECT) {
1057			return Z_OBJ(ex->This);
1058		} else if (ex->func) {
1059			if (ex->func->type != ZEND_INTERNAL_FUNCTION || ex->func->common.scope) {
1060				return NULL;
1061			}
1062		}
1063		ex = ex->prev_execute_data;
1064	}
1065	return NULL;
1066}
1067/* }}} */
1068
1069ZEND_API int zend_eval_stringl(char *str, size_t str_len, zval *retval_ptr, char *string_name) /* {{{ */
1070{
1071	zval pv;
1072	zend_op_array *new_op_array;
1073	uint32_t original_compiler_options;
1074	int retval;
1075
1076	if (retval_ptr) {
1077		ZVAL_NEW_STR(&pv, zend_string_alloc(str_len + sizeof("return ;")-1, 1));
1078		memcpy(Z_STRVAL(pv), "return ", sizeof("return ") - 1);
1079		memcpy(Z_STRVAL(pv) + sizeof("return ") - 1, str, str_len);
1080		Z_STRVAL(pv)[Z_STRLEN(pv) - 1] = ';';
1081		Z_STRVAL(pv)[Z_STRLEN(pv)] = '\0';
1082	} else {
1083		ZVAL_STRINGL(&pv, str, str_len);
1084	}
1085
1086	/*printf("Evaluating '%s'\n", pv.value.str.val);*/
1087
1088	original_compiler_options = CG(compiler_options);
1089	CG(compiler_options) = ZEND_COMPILE_DEFAULT_FOR_EVAL;
1090	new_op_array = zend_compile_string(&pv, string_name);
1091	CG(compiler_options) = original_compiler_options;
1092
1093	if (new_op_array) {
1094		zval local_retval;
1095
1096		EG(no_extensions)=1;
1097
1098		zend_try {
1099			ZVAL_UNDEF(&local_retval);
1100			zend_execute(new_op_array, &local_retval);
1101		} zend_catch {
1102			destroy_op_array(new_op_array);
1103			efree_size(new_op_array, sizeof(zend_op_array));
1104			zend_bailout();
1105		} zend_end_try();
1106
1107		if (Z_TYPE(local_retval) != IS_UNDEF) {
1108			if (retval_ptr) {
1109				ZVAL_COPY_VALUE(retval_ptr, &local_retval);
1110			} else {
1111				zval_ptr_dtor(&local_retval);
1112			}
1113		} else {
1114			if (retval_ptr) {
1115				ZVAL_NULL(retval_ptr);
1116			}
1117		}
1118
1119		EG(no_extensions)=0;
1120		destroy_op_array(new_op_array);
1121		efree_size(new_op_array, sizeof(zend_op_array));
1122		retval = SUCCESS;
1123	} else {
1124		retval = FAILURE;
1125	}
1126	zval_dtor(&pv);
1127	return retval;
1128}
1129/* }}} */
1130
1131ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name) /* {{{ */
1132{
1133	return zend_eval_stringl(str, strlen(str), retval_ptr, string_name);
1134}
1135/* }}} */
1136
1137ZEND_API int zend_eval_stringl_ex(char *str, size_t str_len, zval *retval_ptr, char *string_name, int handle_exceptions) /* {{{ */
1138{
1139	int result;
1140
1141	result = zend_eval_stringl(str, str_len, retval_ptr, string_name);
1142	if (handle_exceptions && EG(exception)) {
1143		zend_exception_error(EG(exception), E_ERROR);
1144		result = FAILURE;
1145	}
1146	return result;
1147}
1148/* }}} */
1149
1150ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name, int handle_exceptions) /* {{{ */
1151{
1152	return zend_eval_stringl_ex(str, strlen(str), retval_ptr, string_name, handle_exceptions);
1153}
1154/* }}} */
1155
1156static void zend_set_timeout_ex(zend_long seconds, int reset_signals);
1157
1158ZEND_API ZEND_NORETURN void zend_timeout(int dummy) /* {{{ */
1159{
1160	EG(timed_out) = 0;
1161	zend_set_timeout_ex(0, 1);
1162	zend_error_noreturn(E_ERROR, "Maximum execution time of %pd second%s exceeded", EG(timeout_seconds), EG(timeout_seconds) == 1 ? "" : "s");
1163}
1164/* }}} */
1165
1166#ifndef ZEND_WIN32
1167static void zend_timeout_handler(int dummy) /* {{{ */
1168{
1169#ifndef ZTS
1170    if (EG(timed_out)) {
1171		/* Die on hard timeout */
1172		const char *error_filename = NULL;
1173		uint error_lineno = 0;
1174		char *log_buffer = NULL;
1175
1176		if (zend_is_compiling()) {
1177			error_filename = ZSTR_VAL(zend_get_compiled_filename());
1178			error_lineno = zend_get_compiled_lineno();
1179		} else if (zend_is_executing()) {
1180			error_filename = zend_get_executed_filename();
1181			if (error_filename[0] == '[') { /* [no active file] */
1182				error_filename = NULL;
1183				error_lineno = 0;
1184			} else {
1185				error_lineno = zend_get_executed_lineno();
1186			}
1187		}
1188		if (!error_filename) {
1189			error_filename = "Unknown";
1190		}
1191
1192		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);
1193		write(2, log_buffer, strlen(log_buffer));
1194		_exit(1);
1195    }
1196#endif
1197
1198	if (zend_on_timeout) {
1199#ifdef ZEND_SIGNALS
1200		/*
1201		   We got here because we got a timeout signal, so we are in a signal handler
1202		   at this point. However, we want to be able to timeout any user-supplied
1203		   shutdown functions, so pretend we are not in a signal handler while we are
1204		   calling these
1205		*/
1206		SIGG(running) = 0;
1207#endif
1208		zend_on_timeout(EG(timeout_seconds));
1209	}
1210
1211	EG(timed_out) = 1;
1212
1213#ifndef ZTS
1214	if (EG(hard_timeout) > 0) {
1215		/* Set hard timeout */
1216		zend_set_timeout_ex(EG(hard_timeout), 1);
1217	}
1218#endif
1219}
1220/* }}} */
1221#endif
1222
1223#ifdef ZEND_WIN32
1224VOID CALLBACK tq_timer_cb(PVOID arg, BOOLEAN timed_out)
1225{
1226	zend_bool *php_timed_out;
1227
1228	/* The doc states it'll be always true, however it theoretically
1229		could be FALSE when the thread was signaled. */
1230	if (!timed_out) {
1231		return;
1232	}
1233
1234	php_timed_out = (zend_bool *)arg;
1235	*php_timed_out = 1;
1236}
1237#endif
1238
1239/* This one doesn't exists on QNX */
1240#ifndef SIGPROF
1241#define SIGPROF 27
1242#endif
1243
1244static void zend_set_timeout_ex(zend_long seconds, int reset_signals) /* {{{ */
1245{
1246
1247#ifdef ZEND_WIN32
1248	if(!seconds) {
1249		return;
1250	}
1251
1252        /* Don't use ChangeTimerQueueTimer() as it will not restart an expired
1253		timer, so we could end up with just an ignored timeout. Instead
1254		delete and recreate. */
1255	if (NULL != tq_timer) {
1256		if (!DeleteTimerQueueTimer(NULL, tq_timer, NULL)) {
1257			tq_timer = NULL;
1258			zend_error_noreturn(E_ERROR, "Could not delete queued timer");
1259			return;
1260		}
1261		tq_timer = NULL;
1262	}
1263
1264	/* XXX passing NULL means the default timer queue provided by the system is used */
1265	if (!CreateTimerQueueTimer(&tq_timer, NULL, (WAITORTIMERCALLBACK)tq_timer_cb, (VOID*)&EG(timed_out), seconds*1000, 0, WT_EXECUTEONLYONCE)) {
1266		tq_timer = NULL;
1267		zend_error_noreturn(E_ERROR, "Could not queue new timer");
1268		return;
1269	}
1270#else
1271#	ifdef HAVE_SETITIMER
1272	{
1273		struct itimerval t_r;		/* timeout requested */
1274		int signo;
1275
1276		if(seconds) {
1277			t_r.it_value.tv_sec = seconds;
1278			t_r.it_value.tv_usec = t_r.it_interval.tv_sec = t_r.it_interval.tv_usec = 0;
1279
1280#	ifdef __CYGWIN__
1281			setitimer(ITIMER_REAL, &t_r, NULL);
1282		}
1283		signo = SIGALRM;
1284#	else
1285			setitimer(ITIMER_PROF, &t_r, NULL);
1286		}
1287		signo = SIGPROF;
1288#	endif
1289
1290		if (reset_signals) {
1291#	ifdef ZEND_SIGNALS
1292			zend_signal(signo, zend_timeout_handler);
1293#	else
1294			sigset_t sigset;
1295#   ifdef HAVE_SIGACTION
1296			struct sigaction act;
1297
1298			act.sa_handler = zend_timeout_handler;
1299			sigemptyset(&act.sa_mask);
1300			act.sa_flags = SA_RESETHAND | SA_NODEFER;
1301			sigaction(signo, &act, NULL);
1302#   else
1303			signal(signo, zend_timeout_handler);
1304#   endif /* HAVE_SIGACTION */
1305			sigemptyset(&sigset);
1306			sigaddset(&sigset, signo);
1307			sigprocmask(SIG_UNBLOCK, &sigset, NULL);
1308#	endif /* ZEND_SIGNALS */
1309		}
1310	}
1311#	endif /* HAVE_SETITIMER */
1312#endif
1313}
1314/* }}} */
1315
1316void zend_set_timeout(zend_long seconds, int reset_signals) /* {{{ */
1317{
1318
1319	EG(timeout_seconds) = seconds;
1320	zend_set_timeout_ex(seconds, reset_signals);
1321	EG(timed_out) = 0;
1322}
1323/* }}} */
1324
1325void zend_unset_timeout(void) /* {{{ */
1326{
1327#ifdef ZEND_WIN32
1328	if (NULL != tq_timer) {
1329		if (!DeleteTimerQueueTimer(NULL, tq_timer, NULL)) {
1330			EG(timed_out) = 0;
1331			tq_timer = NULL;
1332			zend_error_noreturn(E_ERROR, "Could not delete queued timer");
1333			return;
1334		}
1335		tq_timer = NULL;
1336	}
1337	EG(timed_out) = 0;
1338#else
1339#	ifdef HAVE_SETITIMER
1340	if (EG(timeout_seconds)) {
1341		struct itimerval no_timeout;
1342
1343		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;
1344
1345#ifdef __CYGWIN__
1346		setitimer(ITIMER_REAL, &no_timeout, NULL);
1347#else
1348		setitimer(ITIMER_PROF, &no_timeout, NULL);
1349#endif
1350	}
1351#	endif
1352	EG(timed_out) = 0;
1353#endif
1354}
1355/* }}} */
1356
1357zend_class_entry *zend_fetch_class(zend_string *class_name, int fetch_type) /* {{{ */
1358{
1359	zend_class_entry *ce, *scope;
1360	int fetch_sub_type = fetch_type & ZEND_FETCH_CLASS_MASK;
1361
1362check_fetch_type:
1363	switch (fetch_sub_type) {
1364		case ZEND_FETCH_CLASS_SELF:
1365			scope = zend_get_executed_scope();
1366			if (UNEXPECTED(!scope)) {
1367				zend_throw_or_error(fetch_type, NULL, "Cannot access self:: when no class scope is active");
1368			}
1369			return scope;
1370		case ZEND_FETCH_CLASS_PARENT:
1371			scope = zend_get_executed_scope();
1372			if (UNEXPECTED(!scope)) {
1373				zend_throw_or_error(fetch_type, NULL, "Cannot access parent:: when no class scope is active");
1374				return NULL;
1375			}
1376			if (UNEXPECTED(!scope->parent)) {
1377				zend_throw_or_error(fetch_type, NULL, "Cannot access parent:: when current class scope has no parent");
1378			}
1379			return scope->parent;
1380		case ZEND_FETCH_CLASS_STATIC:
1381			ce = zend_get_called_scope(EG(current_execute_data));
1382			if (UNEXPECTED(!ce)) {
1383				zend_throw_or_error(fetch_type, NULL, "Cannot access static:: when no class scope is active");
1384				return NULL;
1385			}
1386			return ce;
1387		case ZEND_FETCH_CLASS_AUTO: {
1388				fetch_sub_type = zend_get_class_fetch_type(class_name);
1389				if (UNEXPECTED(fetch_sub_type != ZEND_FETCH_CLASS_DEFAULT)) {
1390					goto check_fetch_type;
1391				}
1392			}
1393			break;
1394	}
1395
1396	if (fetch_type & ZEND_FETCH_CLASS_NO_AUTOLOAD) {
1397		return zend_lookup_class_ex(class_name, NULL, 0);
1398	} else if ((ce = zend_lookup_class_ex(class_name, NULL, 1)) == NULL) {
1399		if (!(fetch_type & ZEND_FETCH_CLASS_SILENT) && !EG(exception)) {
1400			if (fetch_sub_type == ZEND_FETCH_CLASS_INTERFACE) {
1401				zend_throw_or_error(fetch_type, NULL, "Interface '%s' not found", ZSTR_VAL(class_name));
1402			} else if (fetch_sub_type == ZEND_FETCH_CLASS_TRAIT) {
1403				zend_throw_or_error(fetch_type, NULL, "Trait '%s' not found", ZSTR_VAL(class_name));
1404			} else {
1405				zend_throw_or_error(fetch_type, NULL, "Class '%s' not found", ZSTR_VAL(class_name));
1406			}
1407		}
1408		return NULL;
1409	}
1410	return ce;
1411}
1412/* }}} */
1413
1414zend_class_entry *zend_fetch_class_by_name(zend_string *class_name, const zval *key, int fetch_type) /* {{{ */
1415{
1416	zend_class_entry *ce;
1417
1418	if (fetch_type & ZEND_FETCH_CLASS_NO_AUTOLOAD) {
1419		return zend_lookup_class_ex(class_name, key, 0);
1420	} else if ((ce = zend_lookup_class_ex(class_name, key, 1)) == NULL) {
1421		if ((fetch_type & ZEND_FETCH_CLASS_SILENT) == 0 && !EG(exception)) {
1422			if ((fetch_type & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_INTERFACE) {
1423				zend_throw_or_error(fetch_type, NULL, "Interface '%s' not found", ZSTR_VAL(class_name));
1424			} else if ((fetch_type & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_TRAIT) {
1425				zend_throw_or_error(fetch_type, NULL, "Trait '%s' not found", ZSTR_VAL(class_name));
1426			} else {
1427				zend_throw_or_error(fetch_type, NULL, "Class '%s' not found", ZSTR_VAL(class_name));
1428			}
1429		}
1430		return NULL;
1431	}
1432	return ce;
1433}
1434/* }}} */
1435
1436#define MAX_ABSTRACT_INFO_CNT 3
1437#define MAX_ABSTRACT_INFO_FMT "%s%s%s%s"
1438#define DISPLAY_ABSTRACT_FN(idx) \
1439	ai.afn[idx] ? ZEND_FN_SCOPE_NAME(ai.afn[idx]) : "", \
1440	ai.afn[idx] ? "::" : "", \
1441	ai.afn[idx] ? ZSTR_VAL(ai.afn[idx]->common.function_name) : "", \
1442	ai.afn[idx] && ai.afn[idx + 1] ? ", " : (ai.afn[idx] && ai.cnt > MAX_ABSTRACT_INFO_CNT ? ", ..." : "")
1443
1444typedef struct _zend_abstract_info {
1445	zend_function *afn[MAX_ABSTRACT_INFO_CNT + 1];
1446	int cnt;
1447	int ctor;
1448} zend_abstract_info;
1449
1450static void zend_verify_abstract_class_function(zend_function *fn, zend_abstract_info *ai) /* {{{ */
1451{
1452	if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
1453		if (ai->cnt < MAX_ABSTRACT_INFO_CNT) {
1454			ai->afn[ai->cnt] = fn;
1455		}
1456		if (fn->common.fn_flags & ZEND_ACC_CTOR) {
1457			if (!ai->ctor) {
1458				ai->cnt++;
1459				ai->ctor = 1;
1460			} else {
1461				ai->afn[ai->cnt] = NULL;
1462			}
1463		} else {
1464			ai->cnt++;
1465		}
1466	}
1467}
1468/* }}} */
1469
1470void zend_verify_abstract_class(zend_class_entry *ce) /* {{{ */
1471{
1472	zend_function *func;
1473	zend_abstract_info ai;
1474
1475	if ((ce->ce_flags & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS) && !(ce->ce_flags & (ZEND_ACC_TRAIT | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS))) {
1476		memset(&ai, 0, sizeof(ai));
1477
1478		ZEND_HASH_FOREACH_PTR(&ce->function_table, func) {
1479			zend_verify_abstract_class_function(func, &ai);
1480		} ZEND_HASH_FOREACH_END();
1481
1482		if (ai.cnt) {
1483			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 ")",
1484				ZSTR_VAL(ce->name), ai.cnt,
1485				ai.cnt > 1 ? "s" : "",
1486				DISPLAY_ABSTRACT_FN(0),
1487				DISPLAY_ABSTRACT_FN(1),
1488				DISPLAY_ABSTRACT_FN(2)
1489				);
1490		}
1491	}
1492}
1493/* }}} */
1494
1495ZEND_API int zend_delete_global_variable(zend_string *name) /* {{{ */
1496{
1497    return zend_hash_del_ind(&EG(symbol_table), name);
1498}
1499/* }}} */
1500
1501ZEND_API zend_array *zend_rebuild_symbol_table(void) /* {{{ */
1502{
1503	zend_execute_data *ex;
1504	zend_array *symbol_table;
1505
1506	/* Search for last called user function */
1507	ex = EG(current_execute_data);
1508	while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->common.type))) {
1509		ex = ex->prev_execute_data;
1510	}
1511	if (!ex) {
1512		return NULL;
1513	}
1514	if (ZEND_CALL_INFO(ex) & ZEND_CALL_HAS_SYMBOL_TABLE) {
1515		return ex->symbol_table;
1516	}
1517
1518	ZEND_ADD_CALL_FLAG(ex, ZEND_CALL_HAS_SYMBOL_TABLE);
1519	if (EG(symtable_cache_ptr) >= EG(symtable_cache)) {
1520		/*printf("Cache hit!  Reusing %x\n", symtable_cache[symtable_cache_ptr]);*/
1521		symbol_table = ex->symbol_table = *(EG(symtable_cache_ptr)--);
1522		if (!ex->func->op_array.last_var) {
1523			return symbol_table;
1524		}
1525		zend_hash_extend(symbol_table, ex->func->op_array.last_var, 0);
1526	} else {
1527		symbol_table = ex->symbol_table = emalloc(sizeof(zend_array));
1528		zend_hash_init(symbol_table, ex->func->op_array.last_var, NULL, ZVAL_PTR_DTOR, 0);
1529		if (!ex->func->op_array.last_var) {
1530			return symbol_table;
1531		}
1532		zend_hash_real_init(symbol_table, 0);
1533		/*printf("Cache miss!  Initialized %x\n", EG(active_symbol_table));*/
1534	}
1535	if (EXPECTED(ex->func->op_array.last_var)) {
1536		zend_string **str = ex->func->op_array.vars;
1537		zend_string **end = str + ex->func->op_array.last_var;
1538		zval *var = ZEND_CALL_VAR_NUM(ex, 0);
1539
1540		do {
1541			_zend_hash_append_ind(symbol_table, *str, var);
1542			str++;
1543			var++;
1544		} while (str != end);
1545	}
1546	return symbol_table;
1547}
1548/* }}} */
1549
1550ZEND_API void zend_attach_symbol_table(zend_execute_data *execute_data) /* {{{ */
1551{
1552	zend_op_array *op_array = &execute_data->func->op_array;
1553	HashTable *ht = execute_data->symbol_table;
1554
1555	/* copy real values from symbol table into CV slots and create
1556	   INDIRECT references to CV in symbol table  */
1557	if (EXPECTED(op_array->last_var)) {
1558		zend_string **str = op_array->vars;
1559		zend_string **end = str + op_array->last_var;
1560		zval *var = EX_VAR_NUM(0);
1561
1562		do {
1563			zval *zv = zend_hash_find(ht, *str);
1564
1565			if (zv) {
1566				if (Z_TYPE_P(zv) == IS_INDIRECT) {
1567					zval *val = Z_INDIRECT_P(zv);
1568
1569					ZVAL_COPY_VALUE(var, val);
1570				} else {
1571					ZVAL_COPY_VALUE(var, zv);
1572				}
1573			} else {
1574				ZVAL_UNDEF(var);
1575				zv = zend_hash_add_new(ht, *str, var);
1576			}
1577			ZVAL_INDIRECT(zv, var);
1578			str++;
1579			var++;
1580		} while (str != end);
1581	}
1582}
1583/* }}} */
1584
1585ZEND_API void zend_detach_symbol_table(zend_execute_data *execute_data) /* {{{ */
1586{
1587	zend_op_array *op_array = &execute_data->func->op_array;
1588	HashTable *ht = execute_data->symbol_table;
1589
1590	/* copy real values from CV slots into symbol table */
1591	if (EXPECTED(op_array->last_var)) {
1592		zend_string **str = op_array->vars;
1593		zend_string **end = str + op_array->last_var;
1594		zval *var = EX_VAR_NUM(0);
1595
1596		do {
1597			if (Z_TYPE_P(var) == IS_UNDEF) {
1598				zend_hash_del(ht, *str);
1599			} else {
1600				zend_hash_update(ht, *str, var);
1601				ZVAL_UNDEF(var);
1602			}
1603			str++;
1604			var++;
1605		} while (str != end);
1606	}
1607}
1608/* }}} */
1609
1610ZEND_API int zend_set_local_var(zend_string *name, zval *value, int force) /* {{{ */
1611{
1612	zend_execute_data *execute_data = EG(current_execute_data);
1613
1614	while (execute_data && (!execute_data->func || !ZEND_USER_CODE(execute_data->func->common.type))) {
1615		execute_data = execute_data->prev_execute_data;
1616	}
1617
1618	if (execute_data) {
1619		if (!(EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE)) {
1620			zend_ulong h = zend_string_hash_val(name);
1621			zend_op_array *op_array = &execute_data->func->op_array;
1622
1623			if (EXPECTED(op_array->last_var)) {
1624				zend_string **str = op_array->vars;
1625				zend_string **end = str + op_array->last_var;
1626
1627				do {
1628					if (ZSTR_H(*str) == h &&
1629					    ZSTR_LEN(*str) == ZSTR_LEN(name) &&
1630					    memcmp(ZSTR_VAL(*str), ZSTR_VAL(name), ZSTR_LEN(name)) == 0) {
1631						zval *var = EX_VAR_NUM(str - op_array->vars);
1632						ZVAL_COPY_VALUE(var, value);
1633						return SUCCESS;
1634					}
1635					str++;
1636				} while (str != end);
1637			}
1638			if (force) {
1639				zend_array *symbol_table = zend_rebuild_symbol_table();
1640				if (symbol_table) {
1641					return zend_hash_update(symbol_table, name, value) ? SUCCESS : FAILURE;;
1642				}
1643			}
1644		} else {
1645			return (zend_hash_update_ind(execute_data->symbol_table, name, value) != NULL) ? SUCCESS : FAILURE;
1646		}
1647	}
1648	return FAILURE;
1649}
1650/* }}} */
1651
1652ZEND_API int zend_set_local_var_str(const char *name, size_t len, zval *value, int force) /* {{{ */
1653{
1654	zend_execute_data *execute_data = EG(current_execute_data);
1655
1656	while (execute_data && (!execute_data->func || !ZEND_USER_CODE(execute_data->func->common.type))) {
1657		execute_data = execute_data->prev_execute_data;
1658	}
1659
1660	if (execute_data) {
1661		if (!(EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE)) {
1662			zend_ulong h = zend_hash_func(name, len);
1663			zend_op_array *op_array = &execute_data->func->op_array;
1664			if (EXPECTED(op_array->last_var)) {
1665				zend_string **str = op_array->vars;
1666				zend_string **end = str + op_array->last_var;
1667
1668				do {
1669					if (ZSTR_H(*str) == h &&
1670					    ZSTR_LEN(*str) == len &&
1671					    memcmp(ZSTR_VAL(*str), name, len) == 0) {
1672						zval *var = EX_VAR_NUM(str - op_array->vars);
1673						zval_ptr_dtor(var);
1674						ZVAL_COPY_VALUE(var, value);
1675						return SUCCESS;
1676					}
1677					str++;
1678				} while (str != end);
1679			}
1680			if (force) {
1681				zend_array *symbol_table = zend_rebuild_symbol_table();
1682				if (symbol_table) {
1683					return zend_hash_str_update(symbol_table, name, len, value) ? SUCCESS : FAILURE;;
1684				}
1685			}
1686		} else {
1687			return (zend_hash_str_update_ind(execute_data->symbol_table, name, len, value) != NULL) ? SUCCESS : FAILURE;
1688		}
1689	}
1690	return FAILURE;
1691}
1692/* }}} */
1693
1694ZEND_API int zend_forbid_dynamic_call(const char *func_name) /* {{{ */
1695{
1696	zend_execute_data *ex = EG(current_execute_data);
1697	ZEND_ASSERT(ex != NULL && ex->func != NULL);
1698
1699	if (ZEND_CALL_INFO(ex) & ZEND_CALL_DYNAMIC) {
1700		zend_error(E_WARNING, "Cannot call %s dynamically", func_name);
1701		return FAILURE;
1702	}
1703
1704	return SUCCESS;
1705}
1706/* }}} */
1707
1708/*
1709 * Local variables:
1710 * tab-width: 4
1711 * c-basic-offset: 4
1712 * indent-tabs-mode: t
1713 * End:
1714 */
1715