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