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