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