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