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