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