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