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