xref: /PHP-8.2/Zend/zend_execute_API.c (revision 631bc816)
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_fibers.h"
37 #include "zend_weakrefs.h"
38 #include "zend_inheritance.h"
39 #include "zend_observer.h"
40 #include "zend_call_stack.h"
41 #include "zend_frameless_function.h"
42 #ifdef HAVE_SYS_TIME_H
43 #include <sys/time.h>
44 #endif
45 #ifdef HAVE_UNISTD_H
46 #include <unistd.h>
47 #endif
48 #ifdef ZEND_MAX_EXECUTION_TIMERS
49 #include <sys/syscall.h>
50 #endif
51 
52 ZEND_API void (*zend_execute_ex)(zend_execute_data *execute_data);
53 ZEND_API void (*zend_execute_internal)(zend_execute_data *execute_data, zval *return_value);
54 ZEND_API zend_class_entry *(*zend_autoload)(zend_string *name, zend_string *lc_name);
55 
56 /* true globals */
57 ZEND_API const zend_fcall_info empty_fcall_info = {0};
58 ZEND_API const zend_fcall_info_cache empty_fcall_info_cache = {0};
59 
60 #ifdef ZEND_WIN32
61 ZEND_TLS HANDLE tq_timer = NULL;
62 #endif
63 
64 #if 0&&ZEND_DEBUG
65 static void (*original_sigsegv_handler)(int);
66 static void zend_handle_sigsegv(void) /* {{{ */
67 {
68 	fflush(stdout);
69 	fflush(stderr);
70 	if (original_sigsegv_handler == zend_handle_sigsegv) {
71 		signal(SIGSEGV, original_sigsegv_handler);
72 	} else {
73 		signal(SIGSEGV, SIG_DFL);
74 	}
75 	{
76 
77 		fprintf(stderr, "SIGSEGV caught on opcode %d on opline %d of %s() at %s:%d\n\n",
78 				active_opline->opcode,
79 				active_opline-EG(active_op_array)->opcodes,
80 				get_active_function_name(),
81 				zend_get_executed_filename(),
82 				zend_get_executed_lineno());
83 /* See http://support.microsoft.com/kb/190351 */
84 #ifdef ZEND_WIN32
85 		fflush(stderr);
86 #endif
87 	}
88 	if (original_sigsegv_handler!=zend_handle_sigsegv) {
89 		original_sigsegv_handler(dummy);
90 	}
91 }
92 /* }}} */
93 #endif
94 
zend_extension_activator(zend_extension * extension)95 static void zend_extension_activator(zend_extension *extension) /* {{{ */
96 {
97 	if (extension->activate) {
98 		extension->activate();
99 	}
100 }
101 /* }}} */
102 
zend_extension_deactivator(zend_extension * extension)103 static void zend_extension_deactivator(zend_extension *extension) /* {{{ */
104 {
105 	if (extension->deactivate) {
106 		extension->deactivate();
107 	}
108 }
109 /* }}} */
110 
clean_non_persistent_constant_full(zval * zv)111 static int clean_non_persistent_constant_full(zval *zv) /* {{{ */
112 {
113 	zend_constant *c = Z_PTR_P(zv);
114 	return (ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT) ? ZEND_HASH_APPLY_KEEP : ZEND_HASH_APPLY_REMOVE;
115 }
116 /* }}} */
117 
clean_non_persistent_function_full(zval * zv)118 static int clean_non_persistent_function_full(zval *zv) /* {{{ */
119 {
120 	zend_function *function = Z_PTR_P(zv);
121 	return (function->type == ZEND_INTERNAL_FUNCTION) ? ZEND_HASH_APPLY_KEEP : ZEND_HASH_APPLY_REMOVE;
122 }
123 /* }}} */
124 
clean_non_persistent_class_full(zval * zv)125 static int clean_non_persistent_class_full(zval *zv) /* {{{ */
126 {
127 	zend_class_entry *ce = Z_PTR_P(zv);
128 	return (ce->type == ZEND_INTERNAL_CLASS) ? ZEND_HASH_APPLY_KEEP : ZEND_HASH_APPLY_REMOVE;
129 }
130 /* }}} */
131 
init_executor(void)132 void init_executor(void) /* {{{ */
133 {
134 	zend_init_fpu();
135 
136 	ZVAL_NULL(&EG(uninitialized_zval));
137 	ZVAL_ERROR(&EG(error_zval));
138 /* destroys stack frame, therefore makes core dumps worthless */
139 #if 0&&ZEND_DEBUG
140 	original_sigsegv_handler = signal(SIGSEGV, zend_handle_sigsegv);
141 #endif
142 
143 	EG(symtable_cache_ptr) = EG(symtable_cache);
144 	EG(symtable_cache_limit) = EG(symtable_cache) + SYMTABLE_CACHE_SIZE;
145 	EG(no_extensions) = 0;
146 
147 	EG(function_table) = CG(function_table);
148 	EG(class_table) = CG(class_table);
149 
150 	EG(in_autoload) = NULL;
151 	EG(error_handling) = EH_NORMAL;
152 	EG(flags) = EG_FLAGS_INITIAL;
153 
154 	zend_vm_stack_init();
155 
156 	zend_hash_init(&EG(symbol_table), 64, NULL, ZVAL_PTR_DTOR, 0);
157 
158 	zend_llist_apply(&zend_extensions, (llist_apply_func_t) zend_extension_activator);
159 
160 	zend_hash_init(&EG(included_files), 8, NULL, NULL, 0);
161 
162 	EG(ticks_count) = 0;
163 
164 	ZVAL_UNDEF(&EG(user_error_handler));
165 	ZVAL_UNDEF(&EG(user_exception_handler));
166 
167 	EG(current_execute_data) = NULL;
168 
169 	zend_stack_init(&EG(user_error_handlers_error_reporting), sizeof(int));
170 	zend_stack_init(&EG(user_error_handlers), sizeof(zval));
171 	zend_stack_init(&EG(user_exception_handlers), sizeof(zval));
172 
173 	zend_objects_store_init(&EG(objects_store), 1024);
174 
175 	EG(full_tables_cleanup) = 0;
176 	ZEND_ATOMIC_BOOL_INIT(&EG(vm_interrupt), false);
177 	ZEND_ATOMIC_BOOL_INIT(&EG(timed_out), false);
178 
179 	EG(exception) = NULL;
180 	EG(prev_exception) = NULL;
181 
182 	EG(fake_scope) = NULL;
183 	EG(trampoline).common.function_name = NULL;
184 
185 	EG(ht_iterators_count) = sizeof(EG(ht_iterators_slots)) / sizeof(HashTableIterator);
186 	EG(ht_iterators_used) = 0;
187 	EG(ht_iterators) = EG(ht_iterators_slots);
188 	memset(EG(ht_iterators), 0, sizeof(EG(ht_iterators_slots)));
189 
190 	EG(persistent_constants_count) = EG(zend_constants)->nNumUsed;
191 	EG(persistent_functions_count) = EG(function_table)->nNumUsed;
192 	EG(persistent_classes_count)   = EG(class_table)->nNumUsed;
193 
194 	EG(get_gc_buffer).start = EG(get_gc_buffer).end = EG(get_gc_buffer).cur = NULL;
195 
196 	EG(record_errors) = false;
197 	EG(num_errors) = 0;
198 	EG(errors) = NULL;
199 
200 	EG(filename_override) = NULL;
201 	EG(lineno_override) = -1;
202 
203 	zend_max_execution_timer_init();
204 	zend_fiber_init();
205 	zend_weakrefs_init();
206 
207 	EG(active) = 1;
208 }
209 /* }}} */
210 
zval_call_destructor(zval * zv)211 static int zval_call_destructor(zval *zv) /* {{{ */
212 {
213 	if (Z_TYPE_P(zv) == IS_INDIRECT) {
214 		zv = Z_INDIRECT_P(zv);
215 	}
216 	if (Z_TYPE_P(zv) == IS_OBJECT && Z_REFCOUNT_P(zv) == 1) {
217 		return ZEND_HASH_APPLY_REMOVE;
218 	} else {
219 		return ZEND_HASH_APPLY_KEEP;
220 	}
221 }
222 /* }}} */
223 
zend_unclean_zval_ptr_dtor(zval * zv)224 static void zend_unclean_zval_ptr_dtor(zval *zv) /* {{{ */
225 {
226 	if (Z_TYPE_P(zv) == IS_INDIRECT) {
227 		zv = Z_INDIRECT_P(zv);
228 	}
229 	i_zval_ptr_dtor(zv);
230 }
231 /* }}} */
232 
zend_throw_or_error(int fetch_type,zend_class_entry * exception_ce,const char * format,...)233 static ZEND_COLD void zend_throw_or_error(int fetch_type, zend_class_entry *exception_ce, const char *format, ...) /* {{{ */
234 {
235 	va_list va;
236 	char *message = NULL;
237 
238 	va_start(va, format);
239 	zend_vspprintf(&message, 0, format, va);
240 
241 	if (fetch_type & ZEND_FETCH_CLASS_EXCEPTION) {
242 		zend_throw_error(exception_ce, "%s", message);
243 	} else {
244 		zend_error_noreturn(E_ERROR, "%s", message);
245 	}
246 
247 	efree(message);
248 	va_end(va);
249 }
250 /* }}} */
251 
shutdown_destructors(void)252 void shutdown_destructors(void) /* {{{ */
253 {
254 	if (CG(unclean_shutdown)) {
255 		EG(symbol_table).pDestructor = zend_unclean_zval_ptr_dtor;
256 	}
257 	zend_try {
258 		uint32_t symbols;
259 		do {
260 			symbols = zend_hash_num_elements(&EG(symbol_table));
261 			zend_hash_reverse_apply(&EG(symbol_table), (apply_func_t) zval_call_destructor);
262 		} while (symbols != zend_hash_num_elements(&EG(symbol_table)));
263 		zend_objects_store_call_destructors(&EG(objects_store));
264 	} zend_catch {
265 		/* if we couldn't destruct cleanly, mark all objects as destructed anyway */
266 		zend_objects_store_mark_destructed(&EG(objects_store));
267 	} zend_end_try();
268 }
269 /* }}} */
270 
271 /* Free values held by the executor. */
zend_shutdown_executor_values(bool fast_shutdown)272 ZEND_API void zend_shutdown_executor_values(bool fast_shutdown)
273 {
274 	zend_string *key;
275 	zval *zv;
276 
277 	EG(flags) |= EG_FLAGS_IN_RESOURCE_SHUTDOWN;
278 	zend_try {
279 		zend_close_rsrc_list(&EG(regular_list));
280 	} zend_end_try();
281 
282 	/* No PHP callback functions should be called after this point. */
283 	EG(active) = 0;
284 
285 	if (!fast_shutdown) {
286 		zend_hash_graceful_reverse_destroy(&EG(symbol_table));
287 
288 		/* Constants may contain objects, destroy them before the object store. */
289 		if (EG(full_tables_cleanup)) {
290 			zend_hash_reverse_apply(EG(zend_constants), clean_non_persistent_constant_full);
291 		} else {
292 			ZEND_HASH_MAP_REVERSE_FOREACH_STR_KEY_VAL(EG(zend_constants), key, zv) {
293 				zend_constant *c = Z_PTR_P(zv);
294 				if (_idx == EG(persistent_constants_count)) {
295 					break;
296 				}
297 				zval_ptr_dtor_nogc(&c->value);
298 				if (c->name) {
299 					zend_string_release_ex(c->name, 0);
300 				}
301 				efree(c);
302 				zend_string_release_ex(key, 0);
303 			} ZEND_HASH_MAP_FOREACH_END_DEL();
304 		}
305 
306 		/* Release static properties and static variables prior to the final GC run,
307 		 * as they may hold GC roots. */
308 		ZEND_HASH_MAP_REVERSE_FOREACH_VAL(EG(function_table), zv) {
309 			zend_op_array *op_array = Z_PTR_P(zv);
310 			if (op_array->type == ZEND_INTERNAL_FUNCTION) {
311 				break;
312 			}
313 			if (ZEND_MAP_PTR(op_array->static_variables_ptr)) {
314 				HashTable *ht = ZEND_MAP_PTR_GET(op_array->static_variables_ptr);
315 				if (ht) {
316 					zend_array_destroy(ht);
317 					ZEND_MAP_PTR_SET(op_array->static_variables_ptr, NULL);
318 				}
319 			}
320 		} ZEND_HASH_FOREACH_END();
321 		ZEND_HASH_MAP_REVERSE_FOREACH_VAL(EG(class_table), zv) {
322 			zend_class_entry *ce = Z_PTR_P(zv);
323 
324 			if (ce->default_static_members_count) {
325 				zend_cleanup_internal_class_data(ce);
326 			}
327 
328 			if (ZEND_MAP_PTR(ce->mutable_data)) {
329 				if (ZEND_MAP_PTR_GET_IMM(ce->mutable_data)) {
330 					zend_cleanup_mutable_class_data(ce);
331 				}
332 			} else if (ce->type == ZEND_USER_CLASS && !(ce->ce_flags & ZEND_ACC_IMMUTABLE)) {
333 				/* Constants may contain objects, destroy the values before the object store. */
334 				zend_class_constant *c;
335 				ZEND_HASH_MAP_FOREACH_PTR(&ce->constants_table, c) {
336 					if (c->ce == ce) {
337 						zval_ptr_dtor_nogc(&c->value);
338 						ZVAL_UNDEF(&c->value);
339 					}
340 				} ZEND_HASH_FOREACH_END();
341 
342 				/* properties may contain objects as well */
343 				if (ce->default_properties_table) {
344 					zval *p = ce->default_properties_table;
345 					zval *end = p + ce->default_properties_count;
346 
347 					while (p != end) {
348 						i_zval_ptr_dtor(p);
349 						ZVAL_UNDEF(p);
350 						p++;
351 					}
352 				}
353 			}
354 
355 			if (ce->type == ZEND_USER_CLASS && ce->backed_enum_table) {
356 				ZEND_ASSERT(!(ce->ce_flags & ZEND_ACC_IMMUTABLE));
357 				zend_hash_release(ce->backed_enum_table);
358 				ce->backed_enum_table = NULL;
359 			}
360 
361 			if (ce->ce_flags & ZEND_HAS_STATIC_IN_METHODS) {
362 				zend_op_array *op_array;
363 				ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, op_array) {
364 					if (op_array->type == ZEND_USER_FUNCTION) {
365 						if (ZEND_MAP_PTR(op_array->static_variables_ptr)) {
366 							HashTable *ht = ZEND_MAP_PTR_GET(op_array->static_variables_ptr);
367 							if (ht) {
368 								zend_array_destroy(ht);
369 								ZEND_MAP_PTR_SET(op_array->static_variables_ptr, NULL);
370 							}
371 						}
372 					}
373 				} ZEND_HASH_FOREACH_END();
374 			}
375 		} ZEND_HASH_FOREACH_END();
376 
377 		/* Also release error and exception handlers, which may hold objects. */
378 		if (Z_TYPE(EG(user_error_handler)) != IS_UNDEF) {
379 			zval_ptr_dtor(&EG(user_error_handler));
380 			ZVAL_UNDEF(&EG(user_error_handler));
381 		}
382 
383 		if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) {
384 			zval_ptr_dtor(&EG(user_exception_handler));
385 			ZVAL_UNDEF(&EG(user_exception_handler));
386 		}
387 
388 		zend_stack_clean(&EG(user_error_handlers_error_reporting), NULL, 1);
389 		zend_stack_clean(&EG(user_error_handlers), (void (*)(void *))ZVAL_PTR_DTOR, 1);
390 		zend_stack_clean(&EG(user_exception_handlers), (void (*)(void *))ZVAL_PTR_DTOR, 1);
391 
392 #if ZEND_DEBUG
393 		if (!CG(unclean_shutdown)) {
394 			gc_collect_cycles();
395 		}
396 #endif
397 	} else {
398 		zend_hash_discard(EG(zend_constants), EG(persistent_constants_count));
399 	}
400 
401 	zend_objects_store_free_object_storage(&EG(objects_store), fast_shutdown);
402 }
403 
shutdown_executor(void)404 void shutdown_executor(void) /* {{{ */
405 {
406 	zend_string *key;
407 	zval *zv;
408 #if ZEND_DEBUG
409 	bool fast_shutdown = 0;
410 #else
411 	bool fast_shutdown = is_zend_mm() && !EG(full_tables_cleanup);
412 #endif
413 
414 	zend_try {
415 		zend_stream_shutdown();
416 	} zend_end_try();
417 
418 	zend_shutdown_executor_values(fast_shutdown);
419 
420 	zend_weakrefs_shutdown();
421 	zend_max_execution_timer_shutdown();
422 	zend_fiber_shutdown();
423 
424 	zend_try {
425 		zend_llist_apply(&zend_extensions, (llist_apply_func_t) zend_extension_deactivator);
426 	} zend_end_try();
427 
428 	if (fast_shutdown) {
429 		/* Fast Request Shutdown
430 		 * =====================
431 		 * Zend Memory Manager frees memory by its own. We don't have to free
432 		 * each allocated block separately.
433 		 */
434 		zend_hash_discard(EG(function_table), EG(persistent_functions_count));
435 		zend_hash_discard(EG(class_table), EG(persistent_classes_count));
436 	} else {
437 		zend_vm_stack_destroy();
438 
439 		if (EG(full_tables_cleanup)) {
440 			zend_hash_reverse_apply(EG(function_table), clean_non_persistent_function_full);
441 			zend_hash_reverse_apply(EG(class_table), clean_non_persistent_class_full);
442 		} else {
443 			ZEND_HASH_MAP_REVERSE_FOREACH_STR_KEY_VAL(EG(function_table), key, zv) {
444 				zend_function *func = Z_PTR_P(zv);
445 				if (_idx == EG(persistent_functions_count)) {
446 					break;
447 				}
448 				destroy_op_array(&func->op_array);
449 				zend_string_release_ex(key, 0);
450 			} ZEND_HASH_MAP_FOREACH_END_DEL();
451 
452 			ZEND_HASH_MAP_REVERSE_FOREACH_STR_KEY_VAL(EG(class_table), key, zv) {
453 				if (_idx == EG(persistent_classes_count)) {
454 					break;
455 				}
456 				destroy_zend_class(zv);
457 				zend_string_release_ex(key, 0);
458 			} ZEND_HASH_MAP_FOREACH_END_DEL();
459 		}
460 
461 		while (EG(symtable_cache_ptr) > EG(symtable_cache)) {
462 			EG(symtable_cache_ptr)--;
463 			zend_hash_destroy(*EG(symtable_cache_ptr));
464 			FREE_HASHTABLE(*EG(symtable_cache_ptr));
465 		}
466 
467 		zend_hash_destroy(&EG(included_files));
468 
469 		zend_stack_destroy(&EG(user_error_handlers_error_reporting));
470 		zend_stack_destroy(&EG(user_error_handlers));
471 		zend_stack_destroy(&EG(user_exception_handlers));
472 		zend_objects_store_destroy(&EG(objects_store));
473 		if (EG(in_autoload)) {
474 			zend_hash_destroy(EG(in_autoload));
475 			FREE_HASHTABLE(EG(in_autoload));
476 		}
477 
478 		if (EG(ht_iterators) != EG(ht_iterators_slots)) {
479 			efree(EG(ht_iterators));
480 		}
481 	}
482 
483 #if ZEND_DEBUG
484 	if (EG(ht_iterators_used) && !CG(unclean_shutdown)) {
485 		zend_error(E_WARNING, "Leaked %" PRIu32 " hashtable iterators", EG(ht_iterators_used));
486 	}
487 #endif
488 
489 	/* Check whether anyone is hogging the trampoline. */
490 	ZEND_ASSERT(EG(trampoline).common.function_name == NULL || CG(unclean_shutdown));
491 
492 	EG(ht_iterators_used) = 0;
493 
494 	zend_shutdown_fpu();
495 }
496 /* }}} */
497 
498 /* return class name and "::" or "". */
get_active_class_name(const char ** space)499 ZEND_API const char *get_active_class_name(const char **space) /* {{{ */
500 {
501 	zend_function *func;
502 
503 	if (!zend_is_executing()) {
504 		if (space) {
505 			*space = "";
506 		}
507 		return "";
508 	}
509 
510 	func = EG(current_execute_data)->func;
511 
512 	switch (func->type) {
513 		case ZEND_USER_FUNCTION:
514 		case ZEND_INTERNAL_FUNCTION:
515 		{
516 			zend_class_entry *ce = func->common.scope;
517 
518 			if (space) {
519 				*space = ce ? "::" : "";
520 			}
521 			return ce ? ZSTR_VAL(ce->name) : "";
522 		}
523 		default:
524 			if (space) {
525 				*space = "";
526 			}
527 			return "";
528 	}
529 }
530 /* }}} */
531 
get_active_function_name(void)532 ZEND_API const char *get_active_function_name(void) /* {{{ */
533 {
534 	zend_function *func;
535 
536 	if (!zend_is_executing()) {
537 		return NULL;
538 	}
539 
540 	func = zend_active_function();
541 
542 	switch (func->type) {
543 		case ZEND_USER_FUNCTION: {
544 				zend_string *function_name = func->common.function_name;
545 
546 				if (function_name) {
547 					return ZSTR_VAL(function_name);
548 				} else {
549 					return "main";
550 				}
551 			}
552 			break;
553 		case ZEND_INTERNAL_FUNCTION:
554 			return ZSTR_VAL(func->common.function_name);
555 			break;
556 		default:
557 			return NULL;
558 	}
559 }
560 /* }}} */
561 
zend_active_function_ex(zend_execute_data * execute_data)562 ZEND_API zend_function *zend_active_function_ex(zend_execute_data *execute_data)
563 {
564 	zend_function *func = EX(func);
565 
566 	/* Resolve function if op is a frameless call. */
567 	if (ZEND_USER_CODE(func->type)) {
568 		const zend_op *op = EX(opline);
569 		if (ZEND_OP_IS_FRAMELESS_ICALL(op->opcode)) {
570 			func = ZEND_FLF_FUNC(op);
571 		}
572 	}
573 
574 	return func;
575 }
576 
get_active_function_or_method_name(void)577 ZEND_API zend_string *get_active_function_or_method_name(void) /* {{{ */
578 {
579 	ZEND_ASSERT(zend_is_executing());
580 
581 	return get_function_or_method_name(zend_active_function());
582 }
583 /* }}} */
584 
get_function_or_method_name(const zend_function * func)585 ZEND_API zend_string *get_function_or_method_name(const zend_function *func) /* {{{ */
586 {
587 	if (func->common.scope && func->common.function_name) {
588 		return zend_create_member_string(func->common.scope->name, func->common.function_name);
589 	}
590 
591 	return func->common.function_name ? zend_string_copy(func->common.function_name) : ZSTR_INIT_LITERAL("main", 0);
592 }
593 /* }}} */
594 
get_active_function_arg_name(uint32_t arg_num)595 ZEND_API const char *get_active_function_arg_name(uint32_t arg_num) /* {{{ */
596 {
597 	if (!zend_is_executing()) {
598 		return NULL;
599 	}
600 
601 	zend_function *func = zend_active_function();
602 
603 	return get_function_arg_name(func, arg_num);
604 }
605 /* }}} */
606 
get_function_arg_name(const zend_function * func,uint32_t arg_num)607 ZEND_API const char *get_function_arg_name(const zend_function *func, uint32_t arg_num) /* {{{ */
608 {
609 	if (!func || arg_num == 0 || func->common.num_args < arg_num) {
610 		return NULL;
611 	}
612 
613 	if (func->type == ZEND_USER_FUNCTION || (func->common.fn_flags & ZEND_ACC_USER_ARG_INFO)) {
614 		return ZSTR_VAL(func->common.arg_info[arg_num - 1].name);
615 	} else {
616 		return ((zend_internal_arg_info*) func->common.arg_info)[arg_num - 1].name;
617 	}
618 }
619 /* }}} */
620 
zend_get_executed_filename(void)621 ZEND_API const char *zend_get_executed_filename(void) /* {{{ */
622 {
623 	zend_string *filename = zend_get_executed_filename_ex();
624 	return filename != NULL ? ZSTR_VAL(filename) : "[no active file]";
625 }
626 /* }}} */
627 
zend_get_executed_filename_ex(void)628 ZEND_API zend_string *zend_get_executed_filename_ex(void) /* {{{ */
629 {
630 	zend_string *filename_override = EG(filename_override);
631 	if (filename_override != NULL) {
632 		return filename_override;
633 	}
634 
635 	zend_execute_data *ex = EG(current_execute_data);
636 
637 	while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) {
638 		ex = ex->prev_execute_data;
639 	}
640 	if (ex) {
641 		return ex->func->op_array.filename;
642 	} else {
643 		return NULL;
644 	}
645 }
646 /* }}} */
647 
zend_get_executed_lineno(void)648 ZEND_API uint32_t zend_get_executed_lineno(void) /* {{{ */
649 {
650 	zend_long lineno_override = EG(lineno_override);
651 	if (lineno_override != -1) {
652 		return lineno_override;
653 	}
654 
655 	zend_execute_data *ex = EG(current_execute_data);
656 
657 	while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) {
658 		ex = ex->prev_execute_data;
659 	}
660 	if (ex) {
661 		if (!ex->opline) {
662 			/* Missing SAVE_OPLINE()? Falling back to first line of function */
663 			return ex->func->op_array.opcodes[0].lineno;
664 		}
665 		if (EG(exception) && ex->opline->opcode == ZEND_HANDLE_EXCEPTION &&
666 		    ex->opline->lineno == 0 && EG(opline_before_exception)) {
667 			return EG(opline_before_exception)->lineno;
668 		}
669 		return ex->opline->lineno;
670 	} else {
671 		return 0;
672 	}
673 }
674 /* }}} */
675 
zend_get_executed_scope(void)676 ZEND_API zend_class_entry *zend_get_executed_scope(void) /* {{{ */
677 {
678 	zend_execute_data *ex = EG(current_execute_data);
679 
680 	while (1) {
681 		if (!ex) {
682 			return NULL;
683 		} else if (ex->func && (ZEND_USER_CODE(ex->func->type) || ex->func->common.scope)) {
684 			return ex->func->common.scope;
685 		}
686 		ex = ex->prev_execute_data;
687 	}
688 }
689 /* }}} */
690 
zend_is_executing(void)691 ZEND_API bool zend_is_executing(void) /* {{{ */
692 {
693 	return EG(current_execute_data) != 0;
694 }
695 /* }}} */
696 
zval_update_constant_with_ctx(zval * p,zend_class_entry * scope,zend_ast_evaluate_ctx * ctx)697 ZEND_API zend_result ZEND_FASTCALL zval_update_constant_with_ctx(zval *p, zend_class_entry *scope, zend_ast_evaluate_ctx *ctx)
698 {
699 	if (Z_TYPE_P(p) == IS_CONSTANT_AST) {
700 		zend_ast *ast = Z_ASTVAL_P(p);
701 
702 		if (ast->kind == ZEND_AST_CONSTANT) {
703 			zend_string *name = zend_ast_get_constant_name(ast);
704 			zval *zv = zend_get_constant_ex(name, scope, ast->attr);
705 			if (UNEXPECTED(zv == NULL)) {
706 				return FAILURE;
707 			}
708 
709 			zval_ptr_dtor_nogc(p);
710 			ZVAL_COPY_OR_DUP(p, zv);
711 		} else {
712 			zval tmp;
713 			bool short_circuited;
714 
715 			// Increase the refcount during zend_ast_evaluate to avoid releasing the ast too early
716 			// on nested calls to zval_update_constant_ex which can happen when retriggering ast
717 			// evaluation during autoloading.
718 			zend_ast_ref *ast_ref = Z_AST_P(p);
719 			bool ast_is_refcounted = !(GC_FLAGS(ast_ref) & GC_IMMUTABLE);
720 			if (ast_is_refcounted) {
721 				GC_ADDREF(ast_ref);
722 			}
723 			zend_result result = zend_ast_evaluate_ex(&tmp, ast, scope, &short_circuited, ctx) != SUCCESS;
724 			if (ast_is_refcounted && !GC_DELREF(ast_ref)) {
725 				rc_dtor_func((zend_refcounted *)ast_ref);
726 			}
727 			if (UNEXPECTED(result != SUCCESS)) {
728 				return FAILURE;
729 			}
730 			zval_ptr_dtor_nogc(p);
731 			ZVAL_COPY_VALUE(p, &tmp);
732 		}
733 	}
734 	return SUCCESS;
735 }
736 /* }}} */
737 
zval_update_constant_ex(zval * p,zend_class_entry * scope)738 ZEND_API zend_result ZEND_FASTCALL zval_update_constant_ex(zval *p, zend_class_entry *scope)
739 {
740 	zend_ast_evaluate_ctx ctx = {0};
741 	return zval_update_constant_with_ctx(p, scope, &ctx);
742 }
743 
zval_update_constant(zval * pp)744 ZEND_API zend_result ZEND_FASTCALL zval_update_constant(zval *pp) /* {{{ */
745 {
746 	return zval_update_constant_ex(pp, EG(current_execute_data) ? zend_get_executed_scope() : CG(active_class_entry));
747 }
748 /* }}} */
749 
_call_user_function_impl(zval * object,zval * function_name,zval * retval_ptr,uint32_t param_count,zval params[],HashTable * named_params)750 zend_result _call_user_function_impl(zval *object, zval *function_name, zval *retval_ptr, uint32_t param_count, zval params[], HashTable *named_params) /* {{{ */
751 {
752 	zend_fcall_info fci;
753 
754 	fci.size = sizeof(fci);
755 	if (object) {
756 		ZEND_ASSERT(Z_TYPE_P(object) == IS_OBJECT);
757 		fci.object = Z_OBJ_P(object);
758 	} else {
759 		fci.object = NULL;
760 	}
761 	ZVAL_COPY_VALUE(&fci.function_name, function_name);
762 	fci.retval = retval_ptr;
763 	fci.param_count = param_count;
764 	fci.params = params;
765 	fci.named_params = named_params;
766 
767 	return zend_call_function(&fci, NULL);
768 }
769 /* }}} */
770 
zend_call_function(zend_fcall_info * fci,zend_fcall_info_cache * fci_cache)771 zend_result zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) /* {{{ */
772 {
773 	uint32_t i;
774 	zend_execute_data *call;
775 	zend_fcall_info_cache fci_cache_local;
776 	zend_function *func;
777 	uint32_t call_info;
778 	void *object_or_called_scope;
779 	zend_class_entry *orig_fake_scope;
780 
781 	ZVAL_UNDEF(fci->retval);
782 
783 	if (!EG(active)) {
784 		return FAILURE; /* executor is already inactive */
785 	}
786 
787 	if (EG(exception)) {
788 		if (fci_cache) {
789 			zend_release_fcall_info_cache(fci_cache);
790 		}
791 		return SUCCESS; /* we would result in an instable executor otherwise */
792 	}
793 
794 	ZEND_ASSERT(fci->size == sizeof(zend_fcall_info));
795 
796 	if (!fci_cache || !fci_cache->function_handler) {
797 		char *error = NULL;
798 
799 		if (!fci_cache) {
800 			fci_cache = &fci_cache_local;
801 		}
802 
803 		if (!zend_is_callable_ex(&fci->function_name, fci->object, 0, NULL, fci_cache, &error)) {
804 			ZEND_ASSERT(error && "Should have error if not callable");
805 			zend_string *callable_name
806 				= zend_get_callable_name_ex(&fci->function_name, fci->object);
807 			zend_throw_error(NULL, "Invalid callback %s, %s", ZSTR_VAL(callable_name), error);
808 			efree(error);
809 			zend_string_release_ex(callable_name, 0);
810 			return SUCCESS;
811 		}
812 
813 		ZEND_ASSERT(!error);
814 	}
815 
816 	func = fci_cache->function_handler;
817 	if ((func->common.fn_flags & ZEND_ACC_STATIC) || !fci_cache->object) {
818 		object_or_called_scope = fci_cache->called_scope;
819 		call_info = ZEND_CALL_TOP_FUNCTION | ZEND_CALL_DYNAMIC;
820 	} else {
821 		object_or_called_scope = fci_cache->object;
822 		call_info = ZEND_CALL_TOP_FUNCTION | ZEND_CALL_DYNAMIC | ZEND_CALL_HAS_THIS;
823 	}
824 
825 	call = zend_vm_stack_push_call_frame(call_info,
826 		func, fci->param_count, object_or_called_scope);
827 
828 	if (UNEXPECTED(func->common.fn_flags & ZEND_ACC_DEPRECATED)) {
829 		zend_deprecated_function(func);
830 
831 		if (UNEXPECTED(EG(exception))) {
832 			zend_vm_stack_free_call_frame(call);
833 			return SUCCESS;
834 		}
835 	}
836 
837 	for (i=0; i<fci->param_count; i++) {
838 		zval *param = ZEND_CALL_ARG(call, i+1);
839 		zval *arg = &fci->params[i];
840 		bool must_wrap = 0;
841 		if (UNEXPECTED(Z_ISUNDEF_P(arg))) {
842 			/* Allow forwarding undef slots. This is only used by Closure::__invoke(). */
843 			ZVAL_UNDEF(param);
844 			ZEND_ADD_CALL_FLAG(call, ZEND_CALL_MAY_HAVE_UNDEF);
845 			continue;
846 		}
847 
848 		if (ARG_SHOULD_BE_SENT_BY_REF(func, i + 1)) {
849 			if (UNEXPECTED(!Z_ISREF_P(arg))) {
850 				if (!ARG_MAY_BE_SENT_BY_REF(func, i + 1)) {
851 					/* By-value send is not allowed -- emit a warning,
852 					 * and perform the call with the value wrapped in a reference. */
853 					zend_param_must_be_ref(func, i + 1);
854 					must_wrap = 1;
855 					if (UNEXPECTED(EG(exception))) {
856 						ZEND_CALL_NUM_ARGS(call) = i;
857 cleanup_args:
858 						zend_vm_stack_free_args(call);
859 						zend_vm_stack_free_call_frame(call);
860 						return SUCCESS;
861 					}
862 				}
863 			}
864 		} else {
865 			if (Z_ISREF_P(arg) &&
866 			    !(func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
867 				/* don't separate references for __call */
868 				arg = Z_REFVAL_P(arg);
869 			}
870 		}
871 
872 		if (EXPECTED(!must_wrap)) {
873 			ZVAL_COPY(param, arg);
874 		} else {
875 			Z_TRY_ADDREF_P(arg);
876 			ZVAL_NEW_REF(param, arg);
877 		}
878 	}
879 
880 	if (fci->named_params) {
881 		zend_string *name;
882 		zval *arg;
883 		uint32_t arg_num = ZEND_CALL_NUM_ARGS(call) + 1;
884 		bool have_named_params = 0;
885 		ZEND_HASH_FOREACH_STR_KEY_VAL(fci->named_params, name, arg) {
886 			bool must_wrap = 0;
887 			zval *target;
888 			if (name) {
889 				void *cache_slot[2] = {NULL, NULL};
890 				have_named_params = 1;
891 				target = zend_handle_named_arg(&call, name, &arg_num, cache_slot);
892 				if (!target) {
893 					goto cleanup_args;
894 				}
895 			} else {
896 				if (have_named_params) {
897 					zend_throw_error(NULL,
898 						"Cannot use positional argument after named argument");
899 					goto cleanup_args;
900 				}
901 
902 				zend_vm_stack_extend_call_frame(&call, arg_num - 1, 1);
903 				target = ZEND_CALL_ARG(call, arg_num);
904 			}
905 
906 			if (ARG_SHOULD_BE_SENT_BY_REF(func, arg_num)) {
907 				if (UNEXPECTED(!Z_ISREF_P(arg))) {
908 					if (!ARG_MAY_BE_SENT_BY_REF(func, arg_num)) {
909 						/* By-value send is not allowed -- emit a warning,
910 						 * and perform the call with the value wrapped in a reference. */
911 						zend_param_must_be_ref(func, arg_num);
912 						must_wrap = 1;
913 						if (UNEXPECTED(EG(exception))) {
914 							goto cleanup_args;
915 						}
916 					}
917 				}
918 			} else {
919 				if (Z_ISREF_P(arg) &&
920 					!(func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
921 					/* don't separate references for __call */
922 					arg = Z_REFVAL_P(arg);
923 				}
924 			}
925 
926 			if (EXPECTED(!must_wrap)) {
927 				ZVAL_COPY(target, arg);
928 			} else {
929 				Z_TRY_ADDREF_P(arg);
930 				ZVAL_NEW_REF(target, arg);
931 			}
932 			if (!name) {
933 				ZEND_CALL_NUM_ARGS(call)++;
934 				arg_num++;
935 			}
936 		} ZEND_HASH_FOREACH_END();
937 	}
938 
939 	if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_MAY_HAVE_UNDEF)) {
940 		/* zend_handle_undef_args assumes prev_execute_data is initialized. */
941 		call->prev_execute_data = NULL;
942 		if (zend_handle_undef_args(call) == FAILURE) {
943 			zend_vm_stack_free_args(call);
944 			zend_vm_stack_free_call_frame(call);
945 			return SUCCESS;
946 		}
947 	}
948 
949 	if (UNEXPECTED(func->op_array.fn_flags & ZEND_ACC_CLOSURE)) {
950 		uint32_t call_info;
951 
952 		GC_ADDREF(ZEND_CLOSURE_OBJECT(func));
953 		call_info = ZEND_CALL_CLOSURE;
954 		if (func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) {
955 			call_info |= ZEND_CALL_FAKE_CLOSURE;
956 		}
957 		ZEND_ADD_CALL_FLAG(call, call_info);
958 	}
959 
960 	if (func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
961 		fci_cache->function_handler = NULL;
962 	}
963 
964 	orig_fake_scope = EG(fake_scope);
965 	EG(fake_scope) = NULL;
966 	if (func->type == ZEND_USER_FUNCTION) {
967 		uint32_t orig_jit_trace_num = EG(jit_trace_num);
968 
969 		zend_init_func_execute_data(call, &func->op_array, fci->retval);
970 		ZEND_OBSERVER_FCALL_BEGIN(call);
971 		zend_execute_ex(call);
972 		EG(jit_trace_num) = orig_jit_trace_num;
973 	} else {
974 		ZEND_ASSERT(func->type == ZEND_INTERNAL_FUNCTION);
975 		ZVAL_NULL(fci->retval);
976 		call->prev_execute_data = EG(current_execute_data);
977 		EG(current_execute_data) = call;
978 #if ZEND_DEBUG
979 		bool should_throw = zend_internal_call_should_throw(func, call);
980 #endif
981 		ZEND_OBSERVER_FCALL_BEGIN(call);
982 		if (EXPECTED(zend_execute_internal == NULL)) {
983 			/* saves one function call if zend_execute_internal is not used */
984 			func->internal_function.handler(call, fci->retval);
985 		} else {
986 			zend_execute_internal(call, fci->retval);
987 		}
988 
989 #if ZEND_DEBUG
990 		if (!EG(exception) && call->func) {
991 			if (should_throw) {
992 				zend_internal_call_arginfo_violation(call->func);
993 			}
994 			ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) ||
995 				zend_verify_internal_return_type(call->func, fci->retval));
996 			ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)
997 				? Z_ISREF_P(fci->retval) : !Z_ISREF_P(fci->retval));
998 		}
999 #endif
1000 		ZEND_OBSERVER_FCALL_END(call, fci->retval);
1001 		EG(current_execute_data) = call->prev_execute_data;
1002 		zend_vm_stack_free_args(call);
1003 		if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) {
1004 			zend_array_release(call->extra_named_params);
1005 		}
1006 
1007 		if (EG(exception)) {
1008 			zval_ptr_dtor(fci->retval);
1009 			ZVAL_UNDEF(fci->retval);
1010 		}
1011 
1012 		/* This flag is regularly checked while running user functions, but not internal
1013 		 * So see whether interrupt flag was set while the function was running... */
1014 		if (zend_atomic_bool_exchange_ex(&EG(vm_interrupt), false)) {
1015 			if (zend_atomic_bool_load_ex(&EG(timed_out))) {
1016 				zend_timeout();
1017 			} else if (zend_interrupt_function) {
1018 				zend_interrupt_function(EG(current_execute_data));
1019 			}
1020 		}
1021 
1022 		if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS)) {
1023 			OBJ_RELEASE(Z_OBJ(call->This));
1024 		}
1025 	}
1026 	EG(fake_scope) = orig_fake_scope;
1027 
1028 	zend_vm_stack_free_call_frame(call);
1029 
1030 	if (UNEXPECTED(EG(exception))) {
1031 		if (UNEXPECTED(!EG(current_execute_data))) {
1032 			zend_throw_exception_internal(NULL);
1033 		} else if (EG(current_execute_data)->func &&
1034 		           ZEND_USER_CODE(EG(current_execute_data)->func->common.type)) {
1035 			zend_rethrow_exception(EG(current_execute_data));
1036 		}
1037 	}
1038 
1039 	return SUCCESS;
1040 }
1041 /* }}} */
1042 
zend_call_known_function(zend_function * fn,zend_object * object,zend_class_entry * called_scope,zval * retval_ptr,uint32_t param_count,zval * params,HashTable * named_params)1043 ZEND_API void zend_call_known_function(
1044 		zend_function *fn, zend_object *object, zend_class_entry *called_scope, zval *retval_ptr,
1045 		uint32_t param_count, zval *params, HashTable *named_params)
1046 {
1047 	zval retval;
1048 	zend_fcall_info fci;
1049 	zend_fcall_info_cache fcic;
1050 
1051 	ZEND_ASSERT(fn && "zend_function must be passed!");
1052 
1053 	fci.size = sizeof(fci);
1054 	fci.object = object;
1055 	fci.retval = retval_ptr ? retval_ptr : &retval;
1056 	fci.param_count = param_count;
1057 	fci.params = params;
1058 	fci.named_params = named_params;
1059 	ZVAL_UNDEF(&fci.function_name); /* Unused */
1060 
1061 	fcic.function_handler = fn;
1062 	fcic.object = object;
1063 	fcic.called_scope = called_scope;
1064 
1065 	zend_result result = zend_call_function(&fci, &fcic);
1066 	if (UNEXPECTED(result == FAILURE)) {
1067 		if (!EG(exception)) {
1068 			zend_error_noreturn(E_CORE_ERROR, "Couldn't execute method %s%s%s",
1069 				fn->common.scope ? ZSTR_VAL(fn->common.scope->name) : "",
1070 				fn->common.scope ? "::" : "", ZSTR_VAL(fn->common.function_name));
1071 		}
1072 	}
1073 
1074 	if (!retval_ptr) {
1075 		zval_ptr_dtor(&retval);
1076 	}
1077 }
1078 
zend_call_known_instance_method_with_2_params(zend_function * fn,zend_object * object,zval * retval_ptr,zval * param1,zval * param2)1079 ZEND_API void zend_call_known_instance_method_with_2_params(
1080 		zend_function *fn, zend_object *object, zval *retval_ptr, zval *param1, zval *param2)
1081 {
1082 	zval params[2];
1083 	ZVAL_COPY_VALUE(&params[0], param1);
1084 	ZVAL_COPY_VALUE(&params[1], param2);
1085 	zend_call_known_instance_method(fn, object, retval_ptr, 2, params);
1086 }
1087 
zend_call_method_if_exists(zend_object * object,zend_string * method_name,zval * retval,uint32_t param_count,zval * params)1088 ZEND_API zend_result zend_call_method_if_exists(
1089 		zend_object *object, zend_string *method_name, zval *retval,
1090 		uint32_t param_count, zval *params)
1091 {
1092 	zend_fcall_info fci;
1093 	fci.size = sizeof(zend_fcall_info);
1094 	fci.object = object;
1095 	ZVAL_STR(&fci.function_name, method_name);
1096 	fci.retval = retval;
1097 	fci.param_count = param_count;
1098 	fci.params = params;
1099 	fci.named_params = NULL;
1100 
1101 	zend_fcall_info_cache fcc;
1102 	if (!zend_is_callable_ex(&fci.function_name, fci.object, IS_CALLABLE_SUPPRESS_DEPRECATIONS, NULL, &fcc, NULL)) {
1103 		ZVAL_UNDEF(retval);
1104 		return FAILURE;
1105 	}
1106 
1107 	return zend_call_function(&fci, &fcc);
1108 }
1109 
1110 /* 0-9 a-z A-Z _ \ 0x80-0xff */
1111 static const uint32_t valid_chars[8] = {
1112 	0x00000000,
1113 	0x03ff0000,
1114 	0x97fffffe,
1115 	0x07fffffe,
1116 	0xffffffff,
1117 	0xffffffff,
1118 	0xffffffff,
1119 	0xffffffff,
1120 };
1121 
zend_is_valid_class_name(zend_string * name)1122 ZEND_API bool zend_is_valid_class_name(zend_string *name) {
1123 	for (size_t i = 0; i < ZSTR_LEN(name); i++) {
1124 		unsigned char c = ZSTR_VAL(name)[i];
1125 		if (!ZEND_BIT_TEST(valid_chars, c)) {
1126 			return 0;
1127 		}
1128 	}
1129 	return 1;
1130 }
1131 
zend_lookup_class_ex(zend_string * name,zend_string * key,uint32_t flags)1132 ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, zend_string *key, uint32_t flags) /* {{{ */
1133 {
1134 	zend_class_entry *ce = NULL;
1135 	zval *zv;
1136 	zend_string *lc_name;
1137 	zend_string *autoload_name;
1138 	uint32_t ce_cache = 0;
1139 
1140 	if (ZSTR_HAS_CE_CACHE(name) && ZSTR_VALID_CE_CACHE(name)) {
1141 		ce_cache = GC_REFCOUNT(name);
1142 		ce = GET_CE_CACHE(ce_cache);
1143 		if (EXPECTED(ce)) {
1144 			return ce;
1145 		}
1146 	}
1147 
1148 	if (key) {
1149 		lc_name = key;
1150 	} else {
1151 		if (!ZSTR_LEN(name)) {
1152 			return NULL;
1153 		}
1154 
1155 		if (ZSTR_VAL(name)[0] == '\\') {
1156 			lc_name = zend_string_alloc(ZSTR_LEN(name) - 1, 0);
1157 			zend_str_tolower_copy(ZSTR_VAL(lc_name), ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1);
1158 		} else {
1159 			lc_name = zend_string_tolower(name);
1160 		}
1161 	}
1162 
1163 	zv = zend_hash_find(EG(class_table), lc_name);
1164 	if (zv) {
1165 		if (!key) {
1166 			zend_string_release_ex(lc_name, 0);
1167 		}
1168 		ce = (zend_class_entry*)Z_PTR_P(zv);
1169 		if (UNEXPECTED(!(ce->ce_flags & ZEND_ACC_LINKED))) {
1170 			if ((flags & ZEND_FETCH_CLASS_ALLOW_UNLINKED) ||
1171 				((flags & ZEND_FETCH_CLASS_ALLOW_NEARLY_LINKED) &&
1172 					(ce->ce_flags & ZEND_ACC_NEARLY_LINKED))) {
1173 				if (!CG(unlinked_uses)) {
1174 					ALLOC_HASHTABLE(CG(unlinked_uses));
1175 					zend_hash_init(CG(unlinked_uses), 0, NULL, NULL, 0);
1176 				}
1177 				zend_hash_index_add_empty_element(CG(unlinked_uses), (zend_long)(uintptr_t)ce);
1178 				return ce;
1179 			}
1180 			return NULL;
1181 		}
1182 		/* Don't populate CE_CACHE for mutable classes during compilation.
1183 		 * The class may be freed while persisting. */
1184 		if (ce_cache &&
1185 				(!CG(in_compilation) || (ce->ce_flags & ZEND_ACC_IMMUTABLE))) {
1186 			SET_CE_CACHE(ce_cache, ce);
1187 		}
1188 		return ce;
1189 	}
1190 
1191 	/* The compiler is not-reentrant. Make sure we autoload only during run-time. */
1192 	if ((flags & ZEND_FETCH_CLASS_NO_AUTOLOAD) || zend_is_compiling()) {
1193 		if (!key) {
1194 			zend_string_release_ex(lc_name, 0);
1195 		}
1196 		return NULL;
1197 	}
1198 
1199 	if (!zend_autoload) {
1200 		if (!key) {
1201 			zend_string_release_ex(lc_name, 0);
1202 		}
1203 		return NULL;
1204 	}
1205 
1206 	/* Verify class name before passing it to the autoloader. */
1207 	if (!key && !ZSTR_HAS_CE_CACHE(name) && !zend_is_valid_class_name(name)) {
1208 		zend_string_release_ex(lc_name, 0);
1209 		return NULL;
1210 	}
1211 
1212 	if (EG(in_autoload) == NULL) {
1213 		ALLOC_HASHTABLE(EG(in_autoload));
1214 		zend_hash_init(EG(in_autoload), 8, NULL, NULL, 0);
1215 	}
1216 
1217 	if (zend_hash_add_empty_element(EG(in_autoload), lc_name) == NULL) {
1218 		if (!key) {
1219 			zend_string_release_ex(lc_name, 0);
1220 		}
1221 		return NULL;
1222 	}
1223 
1224 	if (ZSTR_VAL(name)[0] == '\\') {
1225 		autoload_name = zend_string_init(ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1, 0);
1226 	} else {
1227 		autoload_name = zend_string_copy(name);
1228 	}
1229 
1230 	zend_exception_save();
1231 	ce = zend_autoload(autoload_name, lc_name);
1232 	zend_exception_restore();
1233 
1234 	zend_string_release_ex(autoload_name, 0);
1235 	zend_hash_del(EG(in_autoload), lc_name);
1236 
1237 	if (!key) {
1238 		zend_string_release_ex(lc_name, 0);
1239 	}
1240 	if (ce) {
1241 		ZEND_ASSERT(!CG(in_compilation));
1242 		if (ce_cache) {
1243 			SET_CE_CACHE(ce_cache, ce);
1244 		}
1245 	}
1246 	return ce;
1247 }
1248 /* }}} */
1249 
zend_lookup_class(zend_string * name)1250 ZEND_API zend_class_entry *zend_lookup_class(zend_string *name) /* {{{ */
1251 {
1252 	return zend_lookup_class_ex(name, NULL, 0);
1253 }
1254 /* }}} */
1255 
zend_get_called_scope(zend_execute_data * ex)1256 ZEND_API zend_class_entry *zend_get_called_scope(zend_execute_data *ex) /* {{{ */
1257 {
1258 	while (ex) {
1259 		if (Z_TYPE(ex->This) == IS_OBJECT) {
1260 			return Z_OBJCE(ex->This);
1261 		} else if (Z_CE(ex->This)) {
1262 			return Z_CE(ex->This);
1263 		} else if (ex->func) {
1264 			if (ex->func->type != ZEND_INTERNAL_FUNCTION || ex->func->common.scope) {
1265 				return NULL;
1266 			}
1267 		}
1268 		ex = ex->prev_execute_data;
1269 	}
1270 	return NULL;
1271 }
1272 /* }}} */
1273 
zend_get_this_object(zend_execute_data * ex)1274 ZEND_API zend_object *zend_get_this_object(zend_execute_data *ex) /* {{{ */
1275 {
1276 	while (ex) {
1277 		if (Z_TYPE(ex->This) == IS_OBJECT) {
1278 			return Z_OBJ(ex->This);
1279 		} else if (ex->func) {
1280 			if (ex->func->type != ZEND_INTERNAL_FUNCTION || ex->func->common.scope) {
1281 				return NULL;
1282 			}
1283 		}
1284 		ex = ex->prev_execute_data;
1285 	}
1286 	return NULL;
1287 }
1288 /* }}} */
1289 
zend_eval_stringl(const char * str,size_t str_len,zval * retval_ptr,const char * string_name)1290 ZEND_API zend_result zend_eval_stringl(const char *str, size_t str_len, zval *retval_ptr, const char *string_name) /* {{{ */
1291 {
1292 	zend_op_array *new_op_array;
1293 	uint32_t original_compiler_options;
1294 	zend_result retval;
1295 	zend_string *code_str;
1296 
1297 	if (retval_ptr) {
1298 		code_str = zend_string_concat3(
1299 			"return ", sizeof("return ")-1, str, str_len, ";", sizeof(";")-1);
1300 	} else {
1301 		code_str = zend_string_init(str, str_len, 0);
1302 	}
1303 
1304 	/*printf("Evaluating '%s'\n", pv.value.str.val);*/
1305 
1306 	original_compiler_options = CG(compiler_options);
1307 	CG(compiler_options) = ZEND_COMPILE_DEFAULT_FOR_EVAL;
1308 	new_op_array = zend_compile_string(code_str, string_name, ZEND_COMPILE_POSITION_AFTER_OPEN_TAG);
1309 	CG(compiler_options) = original_compiler_options;
1310 
1311 	if (new_op_array) {
1312 		zval local_retval;
1313 
1314 		EG(no_extensions)=1;
1315 
1316 		new_op_array->scope = zend_get_executed_scope();
1317 
1318 		zend_try {
1319 			ZVAL_UNDEF(&local_retval);
1320 			zend_execute(new_op_array, &local_retval);
1321 		} zend_catch {
1322 			destroy_op_array(new_op_array);
1323 			efree_size(new_op_array, sizeof(zend_op_array));
1324 			zend_bailout();
1325 		} zend_end_try();
1326 
1327 		if (Z_TYPE(local_retval) != IS_UNDEF) {
1328 			if (retval_ptr) {
1329 				ZVAL_COPY_VALUE(retval_ptr, &local_retval);
1330 			} else {
1331 				zval_ptr_dtor(&local_retval);
1332 			}
1333 		} else {
1334 			if (retval_ptr) {
1335 				ZVAL_NULL(retval_ptr);
1336 			}
1337 		}
1338 
1339 		EG(no_extensions)=0;
1340 		zend_destroy_static_vars(new_op_array);
1341 		destroy_op_array(new_op_array);
1342 		efree_size(new_op_array, sizeof(zend_op_array));
1343 		retval = SUCCESS;
1344 	} else {
1345 		retval = FAILURE;
1346 	}
1347 	zend_string_release(code_str);
1348 	return retval;
1349 }
1350 /* }}} */
1351 
zend_eval_string(const char * str,zval * retval_ptr,const char * string_name)1352 ZEND_API zend_result zend_eval_string(const char *str, zval *retval_ptr, const char *string_name) /* {{{ */
1353 {
1354 	return zend_eval_stringl(str, strlen(str), retval_ptr, string_name);
1355 }
1356 /* }}} */
1357 
zend_eval_stringl_ex(const char * str,size_t str_len,zval * retval_ptr,const char * string_name,bool handle_exceptions)1358 ZEND_API zend_result zend_eval_stringl_ex(const char *str, size_t str_len, zval *retval_ptr, const char *string_name, bool handle_exceptions) /* {{{ */
1359 {
1360 	zend_result result;
1361 
1362 	result = zend_eval_stringl(str, str_len, retval_ptr, string_name);
1363 	if (handle_exceptions && EG(exception)) {
1364 		result = zend_exception_error(EG(exception), E_ERROR);
1365 	}
1366 	return result;
1367 }
1368 /* }}} */
1369 
zend_eval_string_ex(const char * str,zval * retval_ptr,const char * string_name,bool handle_exceptions)1370 ZEND_API zend_result zend_eval_string_ex(const char *str, zval *retval_ptr, const char *string_name, bool handle_exceptions) /* {{{ */
1371 {
1372 	return zend_eval_stringl_ex(str, strlen(str), retval_ptr, string_name, handle_exceptions);
1373 }
1374 /* }}} */
1375 
1376 static void zend_set_timeout_ex(zend_long seconds, bool reset_signals);
1377 
zend_timeout(void)1378 ZEND_API ZEND_NORETURN void ZEND_FASTCALL zend_timeout(void) /* {{{ */
1379 {
1380 #if defined(PHP_WIN32)
1381 # ifndef ZTS
1382 	/* No action is needed if we're timed out because zero seconds are
1383 	   just ignored. Also, the hard timeout needs to be respected. If the
1384 	   timer is not restarted properly, it could hang in the shutdown
1385 	   function. */
1386 	if (EG(hard_timeout) > 0) {
1387 		zend_atomic_bool_store_ex(&EG(timed_out), false);
1388 		zend_set_timeout_ex(EG(hard_timeout), 1);
1389 		/* XXX Abused, introduce an additional flag if the value needs to be kept. */
1390 		EG(hard_timeout) = 0;
1391 	}
1392 # endif
1393 #else
1394 	zend_atomic_bool_store_ex(&EG(timed_out), false);
1395 	zend_set_timeout_ex(0, 1);
1396 #endif
1397 
1398 	zend_error_noreturn(E_ERROR, "Maximum execution time of " ZEND_LONG_FMT " second%s exceeded", EG(timeout_seconds), EG(timeout_seconds) == 1 ? "" : "s");
1399 }
1400 /* }}} */
1401 
1402 #ifndef ZEND_WIN32
1403 # ifdef ZEND_MAX_EXECUTION_TIMERS
zend_timeout_handler(int dummy,siginfo_t * si,void * uc)1404 static void zend_timeout_handler(int dummy, siginfo_t *si, void *uc) /* {{{ */
1405 {
1406 #ifdef ZTS
1407 	if (!tsrm_is_managed_thread()) {
1408 		fprintf(stderr, "zend_timeout_handler() called in a thread not managed by PHP. The expected signal handler will not be called. This is probably a bug.\n");
1409 
1410 		return;
1411 	}
1412 #endif
1413 
1414 	if (si->si_value.sival_ptr != &EG(max_execution_timer_timer)) {
1415 #ifdef MAX_EXECUTION_TIMERS_DEBUG
1416 		fprintf(stderr, "Executing previous handler (if set) for unexpected signal SIGRTMIN received on thread %d\n", (pid_t) syscall(SYS_gettid));
1417 #endif
1418 
1419 		if (EG(oldact).sa_sigaction) {
1420 			EG(oldact).sa_sigaction(dummy, si, uc);
1421 
1422 			return;
1423 		}
1424 		if (EG(oldact).sa_handler) EG(oldact).sa_handler(dummy);
1425 
1426 		return;
1427 	}
1428 # else
1429 static void zend_timeout_handler(int dummy) /* {{{ */
1430 {
1431 # endif
1432 #ifdef ZTS
1433 	if (!tsrm_is_managed_thread()) {
1434 		fprintf(stderr, "zend_timeout_handler() called in a thread not managed by PHP. The expected signal handler will not be called. This is probably a bug.\n");
1435 
1436 		return;
1437 	}
1438 #else
1439 	if (zend_atomic_bool_load_ex(&EG(timed_out))) {
1440 		/* Die on hard timeout */
1441 		const char *error_filename = NULL;
1442 		uint32_t error_lineno = 0;
1443 		char log_buffer[2048];
1444 		int output_len = 0;
1445 
1446 		if (zend_is_compiling()) {
1447 			error_filename = ZSTR_VAL(zend_get_compiled_filename());
1448 			error_lineno = zend_get_compiled_lineno();
1449 		} else if (zend_is_executing()) {
1450 			error_filename = zend_get_executed_filename();
1451 			if (error_filename[0] == '[') { /* [no active file] */
1452 				error_filename = NULL;
1453 				error_lineno = 0;
1454 			} else {
1455 				error_lineno = zend_get_executed_lineno();
1456 			}
1457 		}
1458 		if (!error_filename) {
1459 			error_filename = "Unknown";
1460 		}
1461 
1462 		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);
1463 		if (output_len > 0) {
1464 			zend_quiet_write(2, log_buffer, MIN(output_len, sizeof(log_buffer)));
1465 		}
1466 		_exit(124);
1467 	}
1468 #endif
1469 
1470 	if (zend_on_timeout) {
1471 		zend_on_timeout(EG(timeout_seconds));
1472 	}
1473 
1474 	zend_atomic_bool_store_ex(&EG(timed_out), true);
1475 	zend_atomic_bool_store_ex(&EG(vm_interrupt), true);
1476 
1477 #ifndef ZTS
1478 	if (EG(hard_timeout) > 0) {
1479 		/* Set hard timeout */
1480 		zend_set_timeout_ex(EG(hard_timeout), 1);
1481 	}
1482 #endif
1483 }
1484 /* }}} */
1485 #endif
1486 
1487 #ifdef ZEND_WIN32
1488 VOID CALLBACK tq_timer_cb(PVOID arg, BOOLEAN timed_out)
1489 {
1490 	zend_executor_globals *eg;
1491 
1492 	/* The doc states it'll be always true, however it theoretically
1493 		could be FALSE when the thread was signaled. */
1494 	if (!timed_out) {
1495 		return;
1496 	}
1497 
1498 	eg = (zend_executor_globals *)arg;
1499 	zend_atomic_bool_store_ex(&eg->timed_out, true);
1500 	zend_atomic_bool_store_ex(&eg->vm_interrupt, true);
1501 }
1502 #endif
1503 
1504 /* This one doesn't exists on QNX */
1505 #ifndef SIGPROF
1506 #define SIGPROF 27
1507 #endif
1508 
1509 static void zend_set_timeout_ex(zend_long seconds, bool reset_signals) /* {{{ */
1510 {
1511 #ifdef ZEND_WIN32
1512 	zend_executor_globals *eg;
1513 
1514 	if (!seconds) {
1515 		return;
1516 	}
1517 
1518 	/* Don't use ChangeTimerQueueTimer() as it will not restart an expired
1519 	 * timer, so we could end up with just an ignored timeout. Instead
1520 	 * delete and recreate. */
1521 	if (NULL != tq_timer) {
1522 		if (!DeleteTimerQueueTimer(NULL, tq_timer, INVALID_HANDLE_VALUE)) {
1523 			tq_timer = NULL;
1524 			zend_error_noreturn(E_ERROR, "Could not delete queued timer");
1525 			return;
1526 		}
1527 		tq_timer = NULL;
1528 	}
1529 
1530 	/* XXX passing NULL means the default timer queue provided by the system is used */
1531 	eg = ZEND_MODULE_GLOBALS_BULK(executor);
1532 	if (!CreateTimerQueueTimer(&tq_timer, NULL, (WAITORTIMERCALLBACK)tq_timer_cb, (VOID*)eg, seconds*1000, 0, WT_EXECUTEONLYONCE)) {
1533 		tq_timer = NULL;
1534 		zend_error_noreturn(E_ERROR, "Could not queue new timer");
1535 		return;
1536 	}
1537 #elif defined(ZEND_MAX_EXECUTION_TIMERS)
1538 	zend_max_execution_timer_settime(seconds);
1539 
1540 	if (reset_signals) {
1541 		sigset_t sigset;
1542 		struct sigaction act;
1543 
1544 		act.sa_sigaction = zend_timeout_handler;
1545 		sigemptyset(&act.sa_mask);
1546 		act.sa_flags = SA_ONSTACK | SA_SIGINFO;
1547 		sigaction(SIGRTMIN, &act, NULL);
1548 		sigemptyset(&sigset);
1549 		sigaddset(&sigset, SIGRTMIN);
1550 		sigprocmask(SIG_UNBLOCK, &sigset, NULL);
1551 	}
1552 #elif defined(HAVE_SETITIMER)
1553 	{
1554 		struct itimerval t_r;		/* timeout requested */
1555 		int signo;
1556 
1557 		if(seconds) {
1558 			t_r.it_value.tv_sec = seconds;
1559 			t_r.it_value.tv_usec = t_r.it_interval.tv_sec = t_r.it_interval.tv_usec = 0;
1560 
1561 # if defined(__CYGWIN__) || defined(__PASE__)
1562 			setitimer(ITIMER_REAL, &t_r, NULL);
1563 		}
1564 		signo = SIGALRM;
1565 # else
1566 			setitimer(ITIMER_PROF, &t_r, NULL);
1567 		}
1568 		signo = SIGPROF;
1569 # endif
1570 
1571 		if (reset_signals) {
1572 # ifdef ZEND_SIGNALS
1573 			zend_signal(signo, zend_timeout_handler);
1574 # else
1575 			sigset_t sigset;
1576 #  ifdef HAVE_SIGACTION
1577 			struct sigaction act;
1578 
1579 			act.sa_handler = zend_timeout_handler;
1580 			sigemptyset(&act.sa_mask);
1581 			act.sa_flags = SA_ONSTACK | SA_RESETHAND | SA_NODEFER;
1582 			sigaction(signo, &act, NULL);
1583 #  else
1584 			signal(signo, zend_timeout_handler);
1585 #  endif /* HAVE_SIGACTION */
1586 			sigemptyset(&sigset);
1587 			sigaddset(&sigset, signo);
1588 			sigprocmask(SIG_UNBLOCK, &sigset, NULL);
1589 # endif /* ZEND_SIGNALS */
1590 		}
1591 	}
1592 #endif /* HAVE_SETITIMER */
1593 }
1594 /* }}} */
1595 
zend_set_timeout(zend_long seconds,bool reset_signals)1596 void zend_set_timeout(zend_long seconds, bool reset_signals) /* {{{ */
1597 {
1598 
1599 	EG(timeout_seconds) = seconds;
1600 	zend_set_timeout_ex(seconds, reset_signals);
1601 	zend_atomic_bool_store_ex(&EG(timed_out), false);
1602 }
1603 /* }}} */
1604 
zend_unset_timeout(void)1605 void zend_unset_timeout(void) /* {{{ */
1606 {
1607 #ifdef ZEND_WIN32
1608 	if (NULL != tq_timer) {
1609 		if (!DeleteTimerQueueTimer(NULL, tq_timer, INVALID_HANDLE_VALUE)) {
1610 			zend_atomic_bool_store_ex(&EG(timed_out), false);
1611 			tq_timer = NULL;
1612 			zend_error_noreturn(E_ERROR, "Could not delete queued timer");
1613 			return;
1614 		}
1615 		tq_timer = NULL;
1616 	}
1617 #elif ZEND_MAX_EXECUTION_TIMERS
1618 	zend_max_execution_timer_settime(0);
1619 #elif defined(HAVE_SETITIMER)
1620 	if (EG(timeout_seconds)) {
1621 		struct itimerval no_timeout;
1622 
1623 		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;
1624 
1625 # if defined(__CYGWIN__) || defined(__PASE__)
1626 		setitimer(ITIMER_REAL, &no_timeout, NULL);
1627 # else
1628 		setitimer(ITIMER_PROF, &no_timeout, NULL);
1629 # endif
1630 	}
1631 #endif
1632 	zend_atomic_bool_store_ex(&EG(timed_out), false);
1633 }
1634 /* }}} */
1635 
report_class_fetch_error(zend_string * class_name,uint32_t fetch_type)1636 static ZEND_COLD void report_class_fetch_error(zend_string *class_name, uint32_t fetch_type)
1637 {
1638 	if (fetch_type & ZEND_FETCH_CLASS_SILENT) {
1639 		return;
1640 	}
1641 
1642 	if (EG(exception)) {
1643 		if (!(fetch_type & ZEND_FETCH_CLASS_EXCEPTION)) {
1644 			zend_exception_uncaught_error("During class fetch");
1645 		}
1646 		return;
1647 	}
1648 
1649 	if ((fetch_type & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_INTERFACE) {
1650 		zend_throw_or_error(fetch_type, NULL, "Interface \"%s\" not found", ZSTR_VAL(class_name));
1651 	} else if ((fetch_type & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_TRAIT) {
1652 		zend_throw_or_error(fetch_type, NULL, "Trait \"%s\" not found", ZSTR_VAL(class_name));
1653 	} else {
1654 		zend_throw_or_error(fetch_type, NULL, "Class \"%s\" not found", ZSTR_VAL(class_name));
1655 	}
1656 }
1657 
zend_fetch_class(zend_string * class_name,uint32_t fetch_type)1658 zend_class_entry *zend_fetch_class(zend_string *class_name, uint32_t fetch_type) /* {{{ */
1659 {
1660 	zend_class_entry *ce, *scope;
1661 	uint32_t fetch_sub_type = fetch_type & ZEND_FETCH_CLASS_MASK;
1662 
1663 check_fetch_type:
1664 	switch (fetch_sub_type) {
1665 		case ZEND_FETCH_CLASS_SELF:
1666 			scope = zend_get_executed_scope();
1667 			if (UNEXPECTED(!scope)) {
1668 				zend_throw_or_error(fetch_type, NULL, "Cannot access \"self\" when no class scope is active");
1669 			}
1670 			return scope;
1671 		case ZEND_FETCH_CLASS_PARENT:
1672 			scope = zend_get_executed_scope();
1673 			if (UNEXPECTED(!scope)) {
1674 				zend_throw_or_error(fetch_type, NULL, "Cannot access \"parent\" when no class scope is active");
1675 				return NULL;
1676 			}
1677 			if (UNEXPECTED(!scope->parent)) {
1678 				zend_throw_or_error(fetch_type, NULL, "Cannot access \"parent\" when current class scope has no parent");
1679 			}
1680 			return scope->parent;
1681 		case ZEND_FETCH_CLASS_STATIC:
1682 			ce = zend_get_called_scope(EG(current_execute_data));
1683 			if (UNEXPECTED(!ce)) {
1684 				zend_throw_or_error(fetch_type, NULL, "Cannot access \"static\" when no class scope is active");
1685 				return NULL;
1686 			}
1687 			return ce;
1688 		case ZEND_FETCH_CLASS_AUTO: {
1689 				fetch_sub_type = zend_get_class_fetch_type(class_name);
1690 				if (UNEXPECTED(fetch_sub_type != ZEND_FETCH_CLASS_DEFAULT)) {
1691 					goto check_fetch_type;
1692 				}
1693 			}
1694 			break;
1695 	}
1696 
1697 	ce = zend_lookup_class_ex(class_name, NULL, fetch_type);
1698 	if (!ce) {
1699 		report_class_fetch_error(class_name, fetch_type);
1700 		return NULL;
1701 	}
1702 	return ce;
1703 }
1704 /* }}} */
1705 
zend_fetch_class_with_scope(zend_string * class_name,uint32_t fetch_type,zend_class_entry * scope)1706 zend_class_entry *zend_fetch_class_with_scope(
1707 		zend_string *class_name, uint32_t fetch_type, zend_class_entry *scope)
1708 {
1709 	zend_class_entry *ce;
1710 	switch (fetch_type & ZEND_FETCH_CLASS_MASK) {
1711 		case ZEND_FETCH_CLASS_SELF:
1712 			if (UNEXPECTED(!scope)) {
1713 				zend_throw_or_error(fetch_type, NULL, "Cannot access \"self\" when no class scope is active");
1714 			}
1715 			return scope;
1716 		case ZEND_FETCH_CLASS_PARENT:
1717 			if (UNEXPECTED(!scope)) {
1718 				zend_throw_or_error(fetch_type, NULL, "Cannot access \"parent\" when no class scope is active");
1719 				return NULL;
1720 			}
1721 			if (UNEXPECTED(!scope->parent)) {
1722 				zend_throw_or_error(fetch_type, NULL, "Cannot access \"parent\" when current class scope has no parent");
1723 			}
1724 			return scope->parent;
1725 		case 0:
1726 			break;
1727 		/* Other fetch types are not supported by this function. */
1728 		EMPTY_SWITCH_DEFAULT_CASE()
1729 	}
1730 
1731 	ce = zend_lookup_class_ex(class_name, NULL, fetch_type);
1732 	if (!ce) {
1733 		report_class_fetch_error(class_name, fetch_type);
1734 		return NULL;
1735 	}
1736 	return ce;
1737 }
1738 
zend_fetch_class_by_name(zend_string * class_name,zend_string * key,uint32_t fetch_type)1739 zend_class_entry *zend_fetch_class_by_name(zend_string *class_name, zend_string *key, uint32_t fetch_type) /* {{{ */
1740 {
1741 	zend_class_entry *ce = zend_lookup_class_ex(class_name, key, fetch_type);
1742 	if (!ce) {
1743 		report_class_fetch_error(class_name, fetch_type);
1744 		return NULL;
1745 	}
1746 	return ce;
1747 }
1748 /* }}} */
1749 
zend_delete_global_variable(zend_string * name)1750 ZEND_API zend_result zend_delete_global_variable(zend_string *name) /* {{{ */
1751 {
1752 	return zend_hash_del_ind(&EG(symbol_table), name);
1753 }
1754 /* }}} */
1755 
zend_rebuild_symbol_table(void)1756 ZEND_API zend_array *zend_rebuild_symbol_table(void) /* {{{ */
1757 {
1758 	zend_execute_data *ex;
1759 	zend_array *symbol_table;
1760 
1761 	/* Search for last called user function */
1762 	ex = EG(current_execute_data);
1763 	while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->common.type))) {
1764 		ex = ex->prev_execute_data;
1765 	}
1766 	if (!ex) {
1767 		return NULL;
1768 	}
1769 	if (ZEND_CALL_INFO(ex) & ZEND_CALL_HAS_SYMBOL_TABLE) {
1770 		return ex->symbol_table;
1771 	}
1772 
1773 	ZEND_ADD_CALL_FLAG(ex, ZEND_CALL_HAS_SYMBOL_TABLE);
1774 	if (EG(symtable_cache_ptr) > EG(symtable_cache)) {
1775 		symbol_table = ex->symbol_table = *(--EG(symtable_cache_ptr));
1776 		if (!ex->func->op_array.last_var) {
1777 			return symbol_table;
1778 		}
1779 		zend_hash_extend(symbol_table, ex->func->op_array.last_var, 0);
1780 	} else {
1781 		symbol_table = ex->symbol_table = zend_new_array(ex->func->op_array.last_var);
1782 		if (!ex->func->op_array.last_var) {
1783 			return symbol_table;
1784 		}
1785 		zend_hash_real_init_mixed(symbol_table);
1786 		/*printf("Cache miss!  Initialized %x\n", EG(active_symbol_table));*/
1787 	}
1788 	if (EXPECTED(ex->func->op_array.last_var)) {
1789 		zend_string **str = ex->func->op_array.vars;
1790 		zend_string **end = str + ex->func->op_array.last_var;
1791 		zval *var = ZEND_CALL_VAR_NUM(ex, 0);
1792 
1793 		do {
1794 			_zend_hash_append_ind(symbol_table, *str, var);
1795 			str++;
1796 			var++;
1797 		} while (str != end);
1798 	}
1799 	return symbol_table;
1800 }
1801 /* }}} */
1802 
zend_attach_symbol_table(zend_execute_data * execute_data)1803 ZEND_API void zend_attach_symbol_table(zend_execute_data *execute_data) /* {{{ */
1804 {
1805 	zend_op_array *op_array = &execute_data->func->op_array;
1806 	HashTable *ht = execute_data->symbol_table;
1807 
1808 	/* copy real values from symbol table into CV slots and create
1809 	   INDIRECT references to CV in symbol table  */
1810 	if (EXPECTED(op_array->last_var)) {
1811 		zend_string **str = op_array->vars;
1812 		zend_string **end = str + op_array->last_var;
1813 		zval *var = EX_VAR_NUM(0);
1814 
1815 		do {
1816 			zval *zv = zend_hash_find_known_hash(ht, *str);
1817 
1818 			if (zv) {
1819 				if (Z_TYPE_P(zv) == IS_INDIRECT) {
1820 					zval *val = Z_INDIRECT_P(zv);
1821 
1822 					ZVAL_COPY_VALUE(var, val);
1823 				} else {
1824 					ZVAL_COPY_VALUE(var, zv);
1825 				}
1826 			} else {
1827 				ZVAL_UNDEF(var);
1828 				zv = zend_hash_add_new(ht, *str, var);
1829 			}
1830 			ZVAL_INDIRECT(zv, var);
1831 			str++;
1832 			var++;
1833 		} while (str != end);
1834 	}
1835 }
1836 /* }}} */
1837 
zend_detach_symbol_table(zend_execute_data * execute_data)1838 ZEND_API void zend_detach_symbol_table(zend_execute_data *execute_data) /* {{{ */
1839 {
1840 	zend_op_array *op_array = &execute_data->func->op_array;
1841 	HashTable *ht = execute_data->symbol_table;
1842 
1843 	/* copy real values from CV slots into symbol table */
1844 	if (EXPECTED(op_array->last_var)) {
1845 		zend_string **str = op_array->vars;
1846 		zend_string **end = str + op_array->last_var;
1847 		zval *var = EX_VAR_NUM(0);
1848 
1849 		do {
1850 			if (Z_TYPE_P(var) == IS_UNDEF) {
1851 				zend_hash_del(ht, *str);
1852 			} else {
1853 				zend_hash_update(ht, *str, var);
1854 				ZVAL_UNDEF(var);
1855 			}
1856 			str++;
1857 			var++;
1858 		} while (str != end);
1859 	}
1860 }
1861 /* }}} */
1862 
zend_set_local_var(zend_string * name,zval * value,bool force)1863 ZEND_API zend_result zend_set_local_var(zend_string *name, zval *value, bool force) /* {{{ */
1864 {
1865 	zend_execute_data *execute_data = EG(current_execute_data);
1866 
1867 	while (execute_data && (!execute_data->func || !ZEND_USER_CODE(execute_data->func->common.type))) {
1868 		execute_data = execute_data->prev_execute_data;
1869 	}
1870 
1871 	if (execute_data) {
1872 		if (!(EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE)) {
1873 			zend_ulong h = zend_string_hash_val(name);
1874 			zend_op_array *op_array = &execute_data->func->op_array;
1875 
1876 			if (EXPECTED(op_array->last_var)) {
1877 				zend_string **str = op_array->vars;
1878 				zend_string **end = str + op_array->last_var;
1879 
1880 				do {
1881 					if (ZSTR_H(*str) == h &&
1882 					    zend_string_equal_content(*str, name)) {
1883 						zval *var = EX_VAR_NUM(str - op_array->vars);
1884 						ZVAL_COPY_VALUE(var, value);
1885 						return SUCCESS;
1886 					}
1887 					str++;
1888 				} while (str != end);
1889 			}
1890 			if (force) {
1891 				zend_array *symbol_table = zend_rebuild_symbol_table();
1892 				if (symbol_table) {
1893 					zend_hash_update(symbol_table, name, value);
1894 					return SUCCESS;
1895 				}
1896 			}
1897 		} else {
1898 			zend_hash_update_ind(execute_data->symbol_table, name, value);
1899 			return SUCCESS;
1900 		}
1901 	}
1902 	return FAILURE;
1903 }
1904 /* }}} */
1905 
zend_set_local_var_str(const char * name,size_t len,zval * value,bool force)1906 ZEND_API zend_result zend_set_local_var_str(const char *name, size_t len, zval *value, bool force) /* {{{ */
1907 {
1908 	zend_execute_data *execute_data = EG(current_execute_data);
1909 
1910 	while (execute_data && (!execute_data->func || !ZEND_USER_CODE(execute_data->func->common.type))) {
1911 		execute_data = execute_data->prev_execute_data;
1912 	}
1913 
1914 	if (execute_data) {
1915 		if (!(EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE)) {
1916 			zend_ulong h = zend_hash_func(name, len);
1917 			zend_op_array *op_array = &execute_data->func->op_array;
1918 			if (EXPECTED(op_array->last_var)) {
1919 				zend_string **str = op_array->vars;
1920 				zend_string **end = str + op_array->last_var;
1921 
1922 				do {
1923 					if (ZSTR_H(*str) == h &&
1924 					    zend_string_equals_cstr(*str, name, len)) {
1925 						zval *var = EX_VAR_NUM(str - op_array->vars);
1926 						zval_ptr_dtor(var);
1927 						ZVAL_COPY_VALUE(var, value);
1928 						return SUCCESS;
1929 					}
1930 					str++;
1931 				} while (str != end);
1932 			}
1933 			if (force) {
1934 				zend_array *symbol_table = zend_rebuild_symbol_table();
1935 				if (symbol_table) {
1936 					zend_hash_str_update(symbol_table, name, len, value);
1937 					return SUCCESS;
1938 				}
1939 			}
1940 		} else {
1941 			zend_hash_str_update_ind(execute_data->symbol_table, name, len, value);
1942 			return SUCCESS;
1943 		}
1944 	}
1945 	return FAILURE;
1946 }
1947 /* }}} */
1948