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