xref: /php-src/Zend/zend_execute_API.c (revision 2c3b56de)
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 						if (ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) {
888 							zend_free_extra_named_params(call->extra_named_params);
889 						}
890 						zend_vm_stack_free_call_frame(call);
891 						zend_release_fcall_info_cache(fci_cache);
892 						return SUCCESS;
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(param, arg);
906 		} else {
907 			Z_TRY_ADDREF_P(arg);
908 			ZVAL_NEW_REF(param, arg);
909 		}
910 	}
911 
912 	if (fci->named_params) {
913 		zend_string *name;
914 		zval *arg;
915 		uint32_t arg_num = ZEND_CALL_NUM_ARGS(call) + 1;
916 		bool have_named_params = 0;
917 		ZEND_HASH_FOREACH_STR_KEY_VAL(fci->named_params, name, arg) {
918 			bool must_wrap = 0;
919 			zval *target;
920 			if (name) {
921 				void *cache_slot[2] = {NULL, NULL};
922 				have_named_params = 1;
923 				target = zend_handle_named_arg(&call, name, &arg_num, cache_slot);
924 				if (!target) {
925 					goto cleanup_args;
926 				}
927 			} else {
928 				if (have_named_params) {
929 					zend_throw_error(NULL,
930 						"Cannot use positional argument after named argument");
931 					goto cleanup_args;
932 				}
933 
934 				zend_vm_stack_extend_call_frame(&call, arg_num - 1, 1);
935 				target = ZEND_CALL_ARG(call, arg_num);
936 			}
937 
938 			if (ARG_SHOULD_BE_SENT_BY_REF(func, arg_num)) {
939 				if (UNEXPECTED(!Z_ISREF_P(arg))) {
940 					if (!ARG_MAY_BE_SENT_BY_REF(func, arg_num)) {
941 						/* By-value send is not allowed -- emit a warning,
942 						 * and perform the call with the value wrapped in a reference. */
943 						zend_param_must_be_ref(func, arg_num);
944 						must_wrap = 1;
945 						if (UNEXPECTED(EG(exception))) {
946 							goto cleanup_args;
947 						}
948 					}
949 				}
950 			} else {
951 				if (Z_ISREF_P(arg) &&
952 					!(func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
953 					/* don't separate references for __call */
954 					arg = Z_REFVAL_P(arg);
955 				}
956 			}
957 
958 			if (EXPECTED(!must_wrap)) {
959 				ZVAL_COPY(target, arg);
960 			} else {
961 				Z_TRY_ADDREF_P(arg);
962 				ZVAL_NEW_REF(target, arg);
963 			}
964 			if (!name) {
965 				ZEND_CALL_NUM_ARGS(call)++;
966 				arg_num++;
967 			}
968 		} ZEND_HASH_FOREACH_END();
969 	}
970 
971 	if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_MAY_HAVE_UNDEF)) {
972 		/* zend_handle_undef_args assumes prev_execute_data is initialized. */
973 		call->prev_execute_data = NULL;
974 		if (zend_handle_undef_args(call) == FAILURE) {
975 			zend_vm_stack_free_args(call);
976 			zend_vm_stack_free_call_frame(call);
977 			return SUCCESS;
978 		}
979 	}
980 
981 	if (UNEXPECTED(func->op_array.fn_flags & ZEND_ACC_CLOSURE)) {
982 		uint32_t call_info;
983 
984 		GC_ADDREF(ZEND_CLOSURE_OBJECT(func));
985 		call_info = ZEND_CALL_CLOSURE;
986 		if (func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) {
987 			call_info |= ZEND_CALL_FAKE_CLOSURE;
988 		}
989 		ZEND_ADD_CALL_FLAG(call, call_info);
990 	}
991 
992 	if (func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
993 		fci_cache->function_handler = NULL;
994 	}
995 
996 	orig_fake_scope = EG(fake_scope);
997 	EG(fake_scope) = NULL;
998 	if (func->type == ZEND_USER_FUNCTION) {
999 		uint32_t orig_jit_trace_num = EG(jit_trace_num);
1000 
1001 		zend_init_func_execute_data(call, &func->op_array, fci->retval);
1002 		ZEND_OBSERVER_FCALL_BEGIN(call);
1003 		zend_execute_ex(call);
1004 		EG(jit_trace_num) = orig_jit_trace_num;
1005 	} else {
1006 		ZEND_ASSERT(func->type == ZEND_INTERNAL_FUNCTION);
1007 		ZVAL_NULL(fci->retval);
1008 		call->prev_execute_data = EG(current_execute_data);
1009 		EG(current_execute_data) = call;
1010 #if ZEND_DEBUG
1011 		bool should_throw = zend_internal_call_should_throw(func, call);
1012 #endif
1013 		ZEND_OBSERVER_FCALL_BEGIN(call);
1014 		if (EXPECTED(zend_execute_internal == NULL)) {
1015 			/* saves one function call if zend_execute_internal is not used */
1016 			func->internal_function.handler(call, fci->retval);
1017 		} else {
1018 			zend_execute_internal(call, fci->retval);
1019 		}
1020 
1021 #if ZEND_DEBUG
1022 		if (!EG(exception) && call->func) {
1023 			if (should_throw) {
1024 				zend_internal_call_arginfo_violation(call->func);
1025 			}
1026 			ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) ||
1027 				zend_verify_internal_return_type(call->func, fci->retval));
1028 			ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)
1029 				? Z_ISREF_P(fci->retval) : !Z_ISREF_P(fci->retval));
1030 		}
1031 #endif
1032 		ZEND_OBSERVER_FCALL_END(call, fci->retval);
1033 		EG(current_execute_data) = call->prev_execute_data;
1034 		zend_vm_stack_free_args(call);
1035 		if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) {
1036 			zend_array_release(call->extra_named_params);
1037 		}
1038 
1039 		if (EG(exception)) {
1040 			zval_ptr_dtor(fci->retval);
1041 			ZVAL_UNDEF(fci->retval);
1042 		}
1043 
1044 		/* This flag is regularly checked while running user functions, but not internal
1045 		 * So see whether interrupt flag was set while the function was running... */
1046 		if (zend_atomic_bool_exchange_ex(&EG(vm_interrupt), false)) {
1047 			if (zend_atomic_bool_load_ex(&EG(timed_out))) {
1048 				zend_timeout();
1049 			} else if (zend_interrupt_function) {
1050 				zend_interrupt_function(EG(current_execute_data));
1051 			}
1052 		}
1053 
1054 		if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS)) {
1055 			OBJ_RELEASE(Z_OBJ(call->This));
1056 		}
1057 	}
1058 	EG(fake_scope) = orig_fake_scope;
1059 
1060 	zend_vm_stack_free_call_frame(call);
1061 
1062 	if (UNEXPECTED(EG(exception))) {
1063 		if (UNEXPECTED(!EG(current_execute_data))) {
1064 			zend_throw_exception_internal(NULL);
1065 		} else if (EG(current_execute_data)->func &&
1066 		           ZEND_USER_CODE(EG(current_execute_data)->func->common.type)) {
1067 			zend_rethrow_exception(EG(current_execute_data));
1068 		}
1069 	}
1070 
1071 	return SUCCESS;
1072 }
1073 /* }}} */
1074 
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)1075 ZEND_API void zend_call_known_function(
1076 		zend_function *fn, zend_object *object, zend_class_entry *called_scope, zval *retval_ptr,
1077 		uint32_t param_count, zval *params, HashTable *named_params)
1078 {
1079 	zval retval;
1080 	zend_fcall_info fci;
1081 	zend_fcall_info_cache fcic;
1082 
1083 	ZEND_ASSERT(fn && "zend_function must be passed!");
1084 
1085 	fci.size = sizeof(fci);
1086 	fci.object = object;
1087 	fci.retval = retval_ptr ? retval_ptr : &retval;
1088 	fci.param_count = param_count;
1089 	fci.params = params;
1090 	fci.named_params = named_params;
1091 	ZVAL_UNDEF(&fci.function_name); /* Unused */
1092 
1093 	fcic.function_handler = fn;
1094 	fcic.object = object;
1095 	fcic.called_scope = called_scope;
1096 
1097 	zend_result result = zend_call_function(&fci, &fcic);
1098 	if (UNEXPECTED(result == FAILURE)) {
1099 		if (!EG(exception)) {
1100 			zend_error_noreturn(E_CORE_ERROR, "Couldn't execute method %s%s%s",
1101 				fn->common.scope ? ZSTR_VAL(fn->common.scope->name) : "",
1102 				fn->common.scope ? "::" : "", ZSTR_VAL(fn->common.function_name));
1103 		}
1104 	}
1105 
1106 	if (!retval_ptr) {
1107 		zval_ptr_dtor(&retval);
1108 	}
1109 }
1110 
zend_call_known_instance_method_with_2_params(zend_function * fn,zend_object * object,zval * retval_ptr,zval * param1,zval * param2)1111 ZEND_API void zend_call_known_instance_method_with_2_params(
1112 		zend_function *fn, zend_object *object, zval *retval_ptr, zval *param1, zval *param2)
1113 {
1114 	zval params[2];
1115 	ZVAL_COPY_VALUE(&params[0], param1);
1116 	ZVAL_COPY_VALUE(&params[1], param2);
1117 	zend_call_known_instance_method(fn, object, retval_ptr, 2, params);
1118 }
1119 
zend_call_method_if_exists(zend_object * object,zend_string * method_name,zval * retval,uint32_t param_count,zval * params)1120 ZEND_API zend_result zend_call_method_if_exists(
1121 		zend_object *object, zend_string *method_name, zval *retval,
1122 		uint32_t param_count, zval *params)
1123 {
1124 	zend_fcall_info fci;
1125 	fci.size = sizeof(zend_fcall_info);
1126 	fci.object = object;
1127 	ZVAL_STR(&fci.function_name, method_name);
1128 	fci.retval = retval;
1129 	fci.param_count = param_count;
1130 	fci.params = params;
1131 	fci.named_params = NULL;
1132 
1133 	zend_fcall_info_cache fcc;
1134 	if (!zend_is_callable_ex(&fci.function_name, fci.object, IS_CALLABLE_SUPPRESS_DEPRECATIONS, NULL, &fcc, NULL)) {
1135 		ZVAL_UNDEF(retval);
1136 		return FAILURE;
1137 	}
1138 
1139 	return zend_call_function(&fci, &fcc);
1140 }
1141 
1142 /* 0-9 a-z A-Z _ \ 0x80-0xff */
1143 static const uint32_t valid_chars[8] = {
1144 	0x00000000,
1145 	0x03ff0000,
1146 	0x97fffffe,
1147 	0x07fffffe,
1148 	0xffffffff,
1149 	0xffffffff,
1150 	0xffffffff,
1151 	0xffffffff,
1152 };
1153 
zend_is_valid_class_name(zend_string * name)1154 ZEND_API bool zend_is_valid_class_name(zend_string *name) {
1155 	for (size_t i = 0; i < ZSTR_LEN(name); i++) {
1156 		unsigned char c = ZSTR_VAL(name)[i];
1157 		if (!ZEND_BIT_TEST(valid_chars, c)) {
1158 			return 0;
1159 		}
1160 	}
1161 	return 1;
1162 }
1163 
zend_lookup_class_ex(zend_string * name,zend_string * key,uint32_t flags)1164 ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, zend_string *key, uint32_t flags) /* {{{ */
1165 {
1166 	zend_class_entry *ce = NULL;
1167 	zval *zv;
1168 	zend_string *lc_name;
1169 	zend_string *autoload_name;
1170 	uint32_t ce_cache = 0;
1171 
1172 	if (ZSTR_HAS_CE_CACHE(name) && ZSTR_VALID_CE_CACHE(name)) {
1173 		ce_cache = GC_REFCOUNT(name);
1174 		ce = GET_CE_CACHE(ce_cache);
1175 		if (EXPECTED(ce)) {
1176 			return ce;
1177 		}
1178 	}
1179 
1180 	if (key) {
1181 		lc_name = key;
1182 	} else {
1183 		if (!ZSTR_LEN(name)) {
1184 			return NULL;
1185 		}
1186 
1187 		if (ZSTR_VAL(name)[0] == '\\') {
1188 			lc_name = zend_string_alloc(ZSTR_LEN(name) - 1, 0);
1189 			zend_str_tolower_copy(ZSTR_VAL(lc_name), ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1);
1190 		} else {
1191 			lc_name = zend_string_tolower(name);
1192 		}
1193 	}
1194 
1195 	zv = zend_hash_find(EG(class_table), lc_name);
1196 	if (zv) {
1197 		if (!key) {
1198 			zend_string_release_ex(lc_name, 0);
1199 		}
1200 		ce = (zend_class_entry*)Z_PTR_P(zv);
1201 		if (UNEXPECTED(!(ce->ce_flags & ZEND_ACC_LINKED))) {
1202 			if ((flags & ZEND_FETCH_CLASS_ALLOW_UNLINKED) ||
1203 				((flags & ZEND_FETCH_CLASS_ALLOW_NEARLY_LINKED) &&
1204 					(ce->ce_flags & ZEND_ACC_NEARLY_LINKED))) {
1205 				if (!CG(unlinked_uses)) {
1206 					ALLOC_HASHTABLE(CG(unlinked_uses));
1207 					zend_hash_init(CG(unlinked_uses), 0, NULL, NULL, 0);
1208 				}
1209 				zend_hash_index_add_empty_element(CG(unlinked_uses), (zend_long)(uintptr_t)ce);
1210 				return ce;
1211 			}
1212 			return NULL;
1213 		}
1214 		/* Don't populate CE_CACHE for mutable classes during compilation.
1215 		 * The class may be freed while persisting. */
1216 		if (ce_cache &&
1217 				(!CG(in_compilation) || (ce->ce_flags & ZEND_ACC_IMMUTABLE))) {
1218 			SET_CE_CACHE(ce_cache, ce);
1219 		}
1220 		return ce;
1221 	}
1222 
1223 	/* The compiler is not-reentrant. Make sure we autoload only during run-time. */
1224 	if ((flags & ZEND_FETCH_CLASS_NO_AUTOLOAD) || zend_is_compiling()) {
1225 		if (!key) {
1226 			zend_string_release_ex(lc_name, 0);
1227 		}
1228 		return NULL;
1229 	}
1230 
1231 	if (!zend_autoload) {
1232 		if (!key) {
1233 			zend_string_release_ex(lc_name, 0);
1234 		}
1235 		return NULL;
1236 	}
1237 
1238 	/* Verify class name before passing it to the autoloader. */
1239 	if (!key && !ZSTR_HAS_CE_CACHE(name) && !zend_is_valid_class_name(name)) {
1240 		zend_string_release_ex(lc_name, 0);
1241 		return NULL;
1242 	}
1243 
1244 	if (EG(in_autoload) == NULL) {
1245 		ALLOC_HASHTABLE(EG(in_autoload));
1246 		zend_hash_init(EG(in_autoload), 8, NULL, NULL, 0);
1247 	}
1248 
1249 	if (zend_hash_add_empty_element(EG(in_autoload), lc_name) == NULL) {
1250 		if (!key) {
1251 			zend_string_release_ex(lc_name, 0);
1252 		}
1253 		return NULL;
1254 	}
1255 
1256 	if (ZSTR_VAL(name)[0] == '\\') {
1257 		autoload_name = zend_string_init(ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1, 0);
1258 	} else {
1259 		autoload_name = zend_string_copy(name);
1260 	}
1261 
1262 	zend_string *previous_filename = EG(filename_override);
1263 	zend_long previous_lineno = EG(lineno_override);
1264 	EG(filename_override) = NULL;
1265 	EG(lineno_override) = -1;
1266 	zend_exception_save();
1267 	ce = zend_autoload(autoload_name, lc_name);
1268 	zend_exception_restore();
1269 	EG(filename_override) = previous_filename;
1270 	EG(lineno_override) = previous_lineno;
1271 
1272 	zend_string_release_ex(autoload_name, 0);
1273 	zend_hash_del(EG(in_autoload), lc_name);
1274 
1275 	if (!key) {
1276 		zend_string_release_ex(lc_name, 0);
1277 	}
1278 	if (ce) {
1279 		ZEND_ASSERT(!CG(in_compilation));
1280 		if (ce_cache) {
1281 			SET_CE_CACHE(ce_cache, ce);
1282 		}
1283 	}
1284 	return ce;
1285 }
1286 /* }}} */
1287 
zend_lookup_class(zend_string * name)1288 ZEND_API zend_class_entry *zend_lookup_class(zend_string *name) /* {{{ */
1289 {
1290 	return zend_lookup_class_ex(name, NULL, 0);
1291 }
1292 /* }}} */
1293 
zend_get_called_scope(zend_execute_data * ex)1294 ZEND_API zend_class_entry *zend_get_called_scope(zend_execute_data *ex) /* {{{ */
1295 {
1296 	while (ex) {
1297 		if (Z_TYPE(ex->This) == IS_OBJECT) {
1298 			return Z_OBJCE(ex->This);
1299 		} else if (Z_CE(ex->This)) {
1300 			return Z_CE(ex->This);
1301 		} else if (ex->func) {
1302 			if (ex->func->type != ZEND_INTERNAL_FUNCTION || ex->func->common.scope) {
1303 				return NULL;
1304 			}
1305 		}
1306 		ex = ex->prev_execute_data;
1307 	}
1308 	return NULL;
1309 }
1310 /* }}} */
1311 
zend_get_this_object(zend_execute_data * ex)1312 ZEND_API zend_object *zend_get_this_object(zend_execute_data *ex) /* {{{ */
1313 {
1314 	while (ex) {
1315 		if (Z_TYPE(ex->This) == IS_OBJECT) {
1316 			return Z_OBJ(ex->This);
1317 		} else if (ex->func) {
1318 			if (ex->func->type != ZEND_INTERNAL_FUNCTION || ex->func->common.scope) {
1319 				return NULL;
1320 			}
1321 		}
1322 		ex = ex->prev_execute_data;
1323 	}
1324 	return NULL;
1325 }
1326 /* }}} */
1327 
zend_eval_stringl(const char * str,size_t str_len,zval * retval_ptr,const char * string_name)1328 ZEND_API zend_result zend_eval_stringl(const char *str, size_t str_len, zval *retval_ptr, const char *string_name) /* {{{ */
1329 {
1330 	zend_op_array *new_op_array;
1331 	uint32_t original_compiler_options;
1332 	zend_result retval;
1333 	zend_string *code_str;
1334 
1335 	if (retval_ptr) {
1336 		code_str = zend_string_concat3(
1337 			"return ", sizeof("return ")-1, str, str_len, ";", sizeof(";")-1);
1338 	} else {
1339 		code_str = zend_string_init(str, str_len, 0);
1340 	}
1341 
1342 	/*printf("Evaluating '%s'\n", pv.value.str.val);*/
1343 
1344 	original_compiler_options = CG(compiler_options);
1345 	CG(compiler_options) = ZEND_COMPILE_DEFAULT_FOR_EVAL;
1346 	new_op_array = zend_compile_string(code_str, string_name, ZEND_COMPILE_POSITION_AFTER_OPEN_TAG);
1347 	CG(compiler_options) = original_compiler_options;
1348 
1349 	if (new_op_array) {
1350 		zval local_retval;
1351 
1352 		EG(no_extensions)=1;
1353 
1354 		new_op_array->scope = zend_get_executed_scope();
1355 
1356 		zend_try {
1357 			ZVAL_UNDEF(&local_retval);
1358 			zend_execute(new_op_array, &local_retval);
1359 		} zend_catch {
1360 			destroy_op_array(new_op_array);
1361 			efree_size(new_op_array, sizeof(zend_op_array));
1362 			zend_bailout();
1363 		} zend_end_try();
1364 
1365 		if (Z_TYPE(local_retval) != IS_UNDEF) {
1366 			if (retval_ptr) {
1367 				ZVAL_COPY_VALUE(retval_ptr, &local_retval);
1368 			} else {
1369 				zval_ptr_dtor(&local_retval);
1370 			}
1371 		} else {
1372 			if (retval_ptr) {
1373 				ZVAL_NULL(retval_ptr);
1374 			}
1375 		}
1376 
1377 		EG(no_extensions)=0;
1378 		zend_destroy_static_vars(new_op_array);
1379 		destroy_op_array(new_op_array);
1380 		efree_size(new_op_array, sizeof(zend_op_array));
1381 		retval = SUCCESS;
1382 	} else {
1383 		retval = FAILURE;
1384 	}
1385 	zend_string_release(code_str);
1386 	return retval;
1387 }
1388 /* }}} */
1389 
zend_eval_string(const char * str,zval * retval_ptr,const char * string_name)1390 ZEND_API zend_result zend_eval_string(const char *str, zval *retval_ptr, const char *string_name) /* {{{ */
1391 {
1392 	return zend_eval_stringl(str, strlen(str), retval_ptr, string_name);
1393 }
1394 /* }}} */
1395 
zend_eval_stringl_ex(const char * str,size_t str_len,zval * retval_ptr,const char * string_name,bool handle_exceptions)1396 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) /* {{{ */
1397 {
1398 	zend_result result;
1399 
1400 	result = zend_eval_stringl(str, str_len, retval_ptr, string_name);
1401 	if (handle_exceptions && EG(exception)) {
1402 		result = zend_exception_error(EG(exception), E_ERROR);
1403 	}
1404 	return result;
1405 }
1406 /* }}} */
1407 
zend_eval_string_ex(const char * str,zval * retval_ptr,const char * string_name,bool handle_exceptions)1408 ZEND_API zend_result zend_eval_string_ex(const char *str, zval *retval_ptr, const char *string_name, bool handle_exceptions) /* {{{ */
1409 {
1410 	return zend_eval_stringl_ex(str, strlen(str), retval_ptr, string_name, handle_exceptions);
1411 }
1412 /* }}} */
1413 
1414 static void zend_set_timeout_ex(zend_long seconds, bool reset_signals);
1415 
zend_timeout(void)1416 ZEND_API ZEND_NORETURN void ZEND_FASTCALL zend_timeout(void) /* {{{ */
1417 {
1418 #if defined(PHP_WIN32)
1419 # ifndef ZTS
1420 	/* No action is needed if we're timed out because zero seconds are
1421 	   just ignored. Also, the hard timeout needs to be respected. If the
1422 	   timer is not restarted properly, it could hang in the shutdown
1423 	   function. */
1424 	if (EG(hard_timeout) > 0) {
1425 		zend_atomic_bool_store_ex(&EG(timed_out), false);
1426 		zend_set_timeout_ex(EG(hard_timeout), 1);
1427 		/* XXX Abused, introduce an additional flag if the value needs to be kept. */
1428 		EG(hard_timeout) = 0;
1429 	}
1430 # endif
1431 #else
1432 	zend_atomic_bool_store_ex(&EG(timed_out), false);
1433 	zend_set_timeout_ex(0, 1);
1434 #endif
1435 
1436 	zend_error_noreturn(E_ERROR, "Maximum execution time of " ZEND_LONG_FMT " second%s exceeded", EG(timeout_seconds), EG(timeout_seconds) == 1 ? "" : "s");
1437 }
1438 /* }}} */
1439 
1440 #ifndef ZEND_WIN32
1441 # ifdef ZEND_MAX_EXECUTION_TIMERS
zend_timeout_handler(int dummy,siginfo_t * si,void * uc)1442 static void zend_timeout_handler(int dummy, siginfo_t *si, void *uc) /* {{{ */
1443 {
1444 #ifdef ZTS
1445 	if (!tsrm_is_managed_thread()) {
1446 		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");
1447 
1448 		return;
1449 	}
1450 #endif
1451 
1452 	if (si->si_value.sival_ptr != &EG(max_execution_timer_timer)) {
1453 #ifdef MAX_EXECUTION_TIMERS_DEBUG
1454 		fprintf(stderr, "Executing previous handler (if set) for unexpected signal SIGRTMIN received on thread %d\n", (pid_t) syscall(SYS_gettid));
1455 #endif
1456 
1457 		if (EG(oldact).sa_sigaction) {
1458 			EG(oldact).sa_sigaction(dummy, si, uc);
1459 
1460 			return;
1461 		}
1462 		if (EG(oldact).sa_handler) EG(oldact).sa_handler(dummy);
1463 
1464 		return;
1465 	}
1466 # else
1467 static void zend_timeout_handler(int dummy) /* {{{ */
1468 {
1469 # endif
1470 #ifdef ZTS
1471 	if (!tsrm_is_managed_thread()) {
1472 		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");
1473 
1474 		return;
1475 	}
1476 #else
1477 	if (zend_atomic_bool_load_ex(&EG(timed_out))) {
1478 		/* Die on hard timeout */
1479 		const char *error_filename = NULL;
1480 		uint32_t error_lineno = 0;
1481 		char log_buffer[2048];
1482 		int output_len = 0;
1483 
1484 		if (zend_is_compiling()) {
1485 			error_filename = ZSTR_VAL(zend_get_compiled_filename());
1486 			error_lineno = zend_get_compiled_lineno();
1487 		} else if (zend_is_executing()) {
1488 			error_filename = zend_get_executed_filename();
1489 			if (error_filename[0] == '[') { /* [no active file] */
1490 				error_filename = NULL;
1491 				error_lineno = 0;
1492 			} else {
1493 				error_lineno = zend_get_executed_lineno();
1494 			}
1495 		}
1496 		if (!error_filename) {
1497 			error_filename = "Unknown";
1498 		}
1499 
1500 		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);
1501 		if (output_len > 0) {
1502 			zend_quiet_write(2, log_buffer, MIN(output_len, sizeof(log_buffer)));
1503 		}
1504 		_exit(124);
1505 	}
1506 #endif
1507 
1508 	if (zend_on_timeout) {
1509 		zend_on_timeout(EG(timeout_seconds));
1510 	}
1511 
1512 	zend_atomic_bool_store_ex(&EG(timed_out), true);
1513 	zend_atomic_bool_store_ex(&EG(vm_interrupt), true);
1514 
1515 #ifndef ZTS
1516 	if (EG(hard_timeout) > 0) {
1517 		/* Set hard timeout */
1518 		zend_set_timeout_ex(EG(hard_timeout), 1);
1519 	}
1520 #endif
1521 }
1522 /* }}} */
1523 #endif
1524 
1525 #ifdef ZEND_WIN32
1526 VOID CALLBACK tq_timer_cb(PVOID arg, BOOLEAN timed_out)
1527 {
1528 	zend_executor_globals *eg;
1529 
1530 	/* The doc states it'll be always true, however it theoretically
1531 		could be FALSE when the thread was signaled. */
1532 	if (!timed_out) {
1533 		return;
1534 	}
1535 
1536 	eg = (zend_executor_globals *)arg;
1537 	zend_atomic_bool_store_ex(&eg->timed_out, true);
1538 	zend_atomic_bool_store_ex(&eg->vm_interrupt, true);
1539 }
1540 #endif
1541 
1542 /* This one doesn't exists on QNX */
1543 #ifndef SIGPROF
1544 #define SIGPROF 27
1545 #endif
1546 
1547 static void zend_set_timeout_ex(zend_long seconds, bool reset_signals) /* {{{ */
1548 {
1549 #ifdef ZEND_WIN32
1550 	zend_executor_globals *eg;
1551 
1552 	if (!seconds) {
1553 		return;
1554 	}
1555 
1556 	/* Don't use ChangeTimerQueueTimer() as it will not restart an expired
1557 	 * timer, so we could end up with just an ignored timeout. Instead
1558 	 * delete and recreate. */
1559 	if (NULL != tq_timer) {
1560 		if (!DeleteTimerQueueTimer(NULL, tq_timer, INVALID_HANDLE_VALUE)) {
1561 			tq_timer = NULL;
1562 			zend_error_noreturn(E_ERROR, "Could not delete queued timer");
1563 			return;
1564 		}
1565 		tq_timer = NULL;
1566 	}
1567 
1568 	/* XXX passing NULL means the default timer queue provided by the system is used */
1569 	eg = ZEND_MODULE_GLOBALS_BULK(executor);
1570 	if (!CreateTimerQueueTimer(&tq_timer, NULL, (WAITORTIMERCALLBACK)tq_timer_cb, (VOID*)eg, seconds*1000, 0, WT_EXECUTEONLYONCE)) {
1571 		tq_timer = NULL;
1572 		zend_error_noreturn(E_ERROR, "Could not queue new timer");
1573 		return;
1574 	}
1575 #elif defined(ZEND_MAX_EXECUTION_TIMERS)
1576 	zend_max_execution_timer_settime(seconds);
1577 
1578 	if (reset_signals) {
1579 		sigset_t sigset;
1580 		struct sigaction act;
1581 
1582 		act.sa_sigaction = zend_timeout_handler;
1583 		sigemptyset(&act.sa_mask);
1584 		act.sa_flags = SA_ONSTACK | SA_SIGINFO;
1585 		sigaction(SIGRTMIN, &act, NULL);
1586 		sigemptyset(&sigset);
1587 		sigaddset(&sigset, SIGRTMIN);
1588 		sigprocmask(SIG_UNBLOCK, &sigset, NULL);
1589 	}
1590 #elif defined(HAVE_SETITIMER)
1591 	{
1592 		struct itimerval t_r;		/* timeout requested */
1593 		int signo;
1594 
1595 		// Prevent EINVAL error
1596 		if (seconds < 0 || seconds > 999999999) {
1597 			seconds = 0;
1598 		}
1599 
1600 		if(seconds) {
1601 			t_r.it_value.tv_sec = seconds;
1602 			t_r.it_value.tv_usec = t_r.it_interval.tv_sec = t_r.it_interval.tv_usec = 0;
1603 
1604 # if defined(__CYGWIN__) || defined(__PASE__) || (defined(__aarch64__) && defined(__APPLE__))
1605 			// ITIMER_PROF is broken in Apple Silicon system with MacOS >= 14
1606 			// See https://openradar.appspot.com/radar?id=5583058442911744.
1607 			setitimer(ITIMER_REAL, &t_r, NULL);
1608 		}
1609 		signo = SIGALRM;
1610 # else
1611 			setitimer(ITIMER_PROF, &t_r, NULL);
1612 		}
1613 		signo = SIGPROF;
1614 # endif
1615 
1616 		if (reset_signals) {
1617 # ifdef ZEND_SIGNALS
1618 			zend_signal(signo, zend_timeout_handler);
1619 # else
1620 			sigset_t sigset;
1621 #  ifdef HAVE_SIGACTION
1622 			struct sigaction act;
1623 
1624 			act.sa_handler = zend_timeout_handler;
1625 			sigemptyset(&act.sa_mask);
1626 			act.sa_flags = SA_ONSTACK | SA_RESETHAND | SA_NODEFER;
1627 			sigaction(signo, &act, NULL);
1628 #  else
1629 			signal(signo, zend_timeout_handler);
1630 #  endif /* HAVE_SIGACTION */
1631 			sigemptyset(&sigset);
1632 			sigaddset(&sigset, signo);
1633 			sigprocmask(SIG_UNBLOCK, &sigset, NULL);
1634 # endif /* ZEND_SIGNALS */
1635 		}
1636 	}
1637 #endif /* HAVE_SETITIMER */
1638 }
1639 /* }}} */
1640 
zend_set_timeout(zend_long seconds,bool reset_signals)1641 void zend_set_timeout(zend_long seconds, bool reset_signals) /* {{{ */
1642 {
1643 
1644 	EG(timeout_seconds) = seconds;
1645 	zend_set_timeout_ex(seconds, reset_signals);
1646 	zend_atomic_bool_store_ex(&EG(timed_out), false);
1647 }
1648 /* }}} */
1649 
zend_unset_timeout(void)1650 void zend_unset_timeout(void) /* {{{ */
1651 {
1652 #ifdef ZEND_WIN32
1653 	if (NULL != tq_timer) {
1654 		if (!DeleteTimerQueueTimer(NULL, tq_timer, INVALID_HANDLE_VALUE)) {
1655 			zend_atomic_bool_store_ex(&EG(timed_out), false);
1656 			tq_timer = NULL;
1657 			zend_error_noreturn(E_ERROR, "Could not delete queued timer");
1658 			return;
1659 		}
1660 		tq_timer = NULL;
1661 	}
1662 #elif defined(ZEND_MAX_EXECUTION_TIMERS)
1663 	zend_max_execution_timer_settime(0);
1664 #elif defined(HAVE_SETITIMER)
1665 	if (EG(timeout_seconds)) {
1666 		struct itimerval no_timeout;
1667 
1668 		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;
1669 
1670 # if defined(__CYGWIN__) || defined(__PASE__) || (defined(__aarch64__) && defined(__APPLE__))
1671 		setitimer(ITIMER_REAL, &no_timeout, NULL);
1672 # else
1673 		setitimer(ITIMER_PROF, &no_timeout, NULL);
1674 # endif
1675 	}
1676 #endif
1677 	zend_atomic_bool_store_ex(&EG(timed_out), false);
1678 }
1679 /* }}} */
1680 
report_class_fetch_error(zend_string * class_name,uint32_t fetch_type)1681 static ZEND_COLD void report_class_fetch_error(zend_string *class_name, uint32_t fetch_type)
1682 {
1683 	if (fetch_type & ZEND_FETCH_CLASS_SILENT) {
1684 		return;
1685 	}
1686 
1687 	if (EG(exception)) {
1688 		if (!(fetch_type & ZEND_FETCH_CLASS_EXCEPTION)) {
1689 			zend_exception_uncaught_error("During class fetch");
1690 		}
1691 		return;
1692 	}
1693 
1694 	if ((fetch_type & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_INTERFACE) {
1695 		zend_throw_or_error(fetch_type, NULL, "Interface \"%s\" not found", ZSTR_VAL(class_name));
1696 	} else if ((fetch_type & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_TRAIT) {
1697 		zend_throw_or_error(fetch_type, NULL, "Trait \"%s\" not found", ZSTR_VAL(class_name));
1698 	} else {
1699 		zend_throw_or_error(fetch_type, NULL, "Class \"%s\" not found", ZSTR_VAL(class_name));
1700 	}
1701 }
1702 
zend_fetch_class(zend_string * class_name,uint32_t fetch_type)1703 zend_class_entry *zend_fetch_class(zend_string *class_name, uint32_t fetch_type) /* {{{ */
1704 {
1705 	zend_class_entry *ce, *scope;
1706 	uint32_t fetch_sub_type = fetch_type & ZEND_FETCH_CLASS_MASK;
1707 
1708 check_fetch_type:
1709 	switch (fetch_sub_type) {
1710 		case ZEND_FETCH_CLASS_SELF:
1711 			scope = zend_get_executed_scope();
1712 			if (UNEXPECTED(!scope)) {
1713 				zend_throw_or_error(fetch_type, NULL, "Cannot access \"self\" when no class scope is active");
1714 			}
1715 			return scope;
1716 		case ZEND_FETCH_CLASS_PARENT:
1717 			scope = zend_get_executed_scope();
1718 			if (UNEXPECTED(!scope)) {
1719 				zend_throw_or_error(fetch_type, NULL, "Cannot access \"parent\" when no class scope is active");
1720 				return NULL;
1721 			}
1722 			if (UNEXPECTED(!scope->parent)) {
1723 				zend_throw_or_error(fetch_type, NULL, "Cannot access \"parent\" when current class scope has no parent");
1724 			}
1725 			return scope->parent;
1726 		case ZEND_FETCH_CLASS_STATIC:
1727 			ce = zend_get_called_scope(EG(current_execute_data));
1728 			if (UNEXPECTED(!ce)) {
1729 				zend_throw_or_error(fetch_type, NULL, "Cannot access \"static\" when no class scope is active");
1730 				return NULL;
1731 			}
1732 			return ce;
1733 		case ZEND_FETCH_CLASS_AUTO: {
1734 				fetch_sub_type = zend_get_class_fetch_type(class_name);
1735 				if (UNEXPECTED(fetch_sub_type != ZEND_FETCH_CLASS_DEFAULT)) {
1736 					goto check_fetch_type;
1737 				}
1738 			}
1739 			break;
1740 	}
1741 
1742 	ce = zend_lookup_class_ex(class_name, NULL, fetch_type);
1743 	if (!ce) {
1744 		report_class_fetch_error(class_name, fetch_type);
1745 		return NULL;
1746 	}
1747 	return ce;
1748 }
1749 /* }}} */
1750 
zend_fetch_class_with_scope(zend_string * class_name,uint32_t fetch_type,zend_class_entry * scope)1751 zend_class_entry *zend_fetch_class_with_scope(
1752 		zend_string *class_name, uint32_t fetch_type, zend_class_entry *scope)
1753 {
1754 	zend_class_entry *ce;
1755 	switch (fetch_type & ZEND_FETCH_CLASS_MASK) {
1756 		case ZEND_FETCH_CLASS_SELF:
1757 			if (UNEXPECTED(!scope)) {
1758 				zend_throw_or_error(fetch_type, NULL, "Cannot access \"self\" when no class scope is active");
1759 			}
1760 			return scope;
1761 		case ZEND_FETCH_CLASS_PARENT:
1762 			if (UNEXPECTED(!scope)) {
1763 				zend_throw_or_error(fetch_type, NULL, "Cannot access \"parent\" when no class scope is active");
1764 				return NULL;
1765 			}
1766 			if (UNEXPECTED(!scope->parent)) {
1767 				zend_throw_or_error(fetch_type, NULL, "Cannot access \"parent\" when current class scope has no parent");
1768 			}
1769 			return scope->parent;
1770 		case 0:
1771 			break;
1772 		/* Other fetch types are not supported by this function. */
1773 		EMPTY_SWITCH_DEFAULT_CASE()
1774 	}
1775 
1776 	ce = zend_lookup_class_ex(class_name, NULL, fetch_type);
1777 	if (!ce) {
1778 		report_class_fetch_error(class_name, fetch_type);
1779 		return NULL;
1780 	}
1781 	return ce;
1782 }
1783 
zend_fetch_class_by_name(zend_string * class_name,zend_string * key,uint32_t fetch_type)1784 zend_class_entry *zend_fetch_class_by_name(zend_string *class_name, zend_string *key, uint32_t fetch_type) /* {{{ */
1785 {
1786 	zend_class_entry *ce = zend_lookup_class_ex(class_name, key, fetch_type);
1787 	if (!ce) {
1788 		report_class_fetch_error(class_name, fetch_type);
1789 		return NULL;
1790 	}
1791 	return ce;
1792 }
1793 /* }}} */
1794 
zend_delete_global_variable(zend_string * name)1795 ZEND_API zend_result zend_delete_global_variable(zend_string *name) /* {{{ */
1796 {
1797 	return zend_hash_del_ind(&EG(symbol_table), name);
1798 }
1799 /* }}} */
1800 
zend_rebuild_symbol_table(void)1801 ZEND_API zend_array *zend_rebuild_symbol_table(void) /* {{{ */
1802 {
1803 	zend_execute_data *ex;
1804 	zend_array *symbol_table;
1805 
1806 	/* Search for last called user function */
1807 	ex = EG(current_execute_data);
1808 	while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->common.type))) {
1809 		ex = ex->prev_execute_data;
1810 	}
1811 	if (!ex) {
1812 		return NULL;
1813 	}
1814 	if (ZEND_CALL_INFO(ex) & ZEND_CALL_HAS_SYMBOL_TABLE) {
1815 		return ex->symbol_table;
1816 	}
1817 
1818 	ZEND_ADD_CALL_FLAG(ex, ZEND_CALL_HAS_SYMBOL_TABLE);
1819 	if (EG(symtable_cache_ptr) > EG(symtable_cache)) {
1820 		symbol_table = ex->symbol_table = *(--EG(symtable_cache_ptr));
1821 		if (!ex->func->op_array.last_var) {
1822 			return symbol_table;
1823 		}
1824 		zend_hash_extend(symbol_table, ex->func->op_array.last_var, 0);
1825 	} else {
1826 		symbol_table = ex->symbol_table = zend_new_array(ex->func->op_array.last_var);
1827 		if (!ex->func->op_array.last_var) {
1828 			return symbol_table;
1829 		}
1830 		zend_hash_real_init_mixed(symbol_table);
1831 		/*printf("Cache miss!  Initialized %x\n", EG(active_symbol_table));*/
1832 	}
1833 	if (EXPECTED(ex->func->op_array.last_var)) {
1834 		zend_string **str = ex->func->op_array.vars;
1835 		zend_string **end = str + ex->func->op_array.last_var;
1836 		zval *var = ZEND_CALL_VAR_NUM(ex, 0);
1837 
1838 		do {
1839 			_zend_hash_append_ind(symbol_table, *str, var);
1840 			str++;
1841 			var++;
1842 		} while (str != end);
1843 	}
1844 	return symbol_table;
1845 }
1846 /* }}} */
1847 
zend_attach_symbol_table(zend_execute_data * execute_data)1848 ZEND_API void zend_attach_symbol_table(zend_execute_data *execute_data) /* {{{ */
1849 {
1850 	zend_op_array *op_array = &execute_data->func->op_array;
1851 	HashTable *ht = execute_data->symbol_table;
1852 
1853 	/* copy real values from symbol table into CV slots and create
1854 	   INDIRECT references to CV in symbol table  */
1855 	if (EXPECTED(op_array->last_var)) {
1856 		zend_string **str = op_array->vars;
1857 		zend_string **end = str + op_array->last_var;
1858 		zval *var = EX_VAR_NUM(0);
1859 
1860 		do {
1861 			zval *zv = zend_hash_find_known_hash(ht, *str);
1862 
1863 			if (zv) {
1864 				if (Z_TYPE_P(zv) == IS_INDIRECT) {
1865 					zval *val = Z_INDIRECT_P(zv);
1866 
1867 					ZVAL_COPY_VALUE(var, val);
1868 				} else {
1869 					ZVAL_COPY_VALUE(var, zv);
1870 				}
1871 			} else {
1872 				ZVAL_UNDEF(var);
1873 				zv = zend_hash_add_new(ht, *str, var);
1874 			}
1875 			ZVAL_INDIRECT(zv, var);
1876 			str++;
1877 			var++;
1878 		} while (str != end);
1879 	}
1880 }
1881 /* }}} */
1882 
zend_detach_symbol_table(zend_execute_data * execute_data)1883 ZEND_API void zend_detach_symbol_table(zend_execute_data *execute_data) /* {{{ */
1884 {
1885 	zend_op_array *op_array = &execute_data->func->op_array;
1886 	HashTable *ht = execute_data->symbol_table;
1887 
1888 	/* copy real values from CV slots into symbol table */
1889 	if (EXPECTED(op_array->last_var)) {
1890 		zend_string **str = op_array->vars;
1891 		zend_string **end = str + op_array->last_var;
1892 		zval *var = EX_VAR_NUM(0);
1893 
1894 		do {
1895 			if (Z_TYPE_P(var) == IS_UNDEF) {
1896 				zend_hash_del(ht, *str);
1897 			} else {
1898 				zend_hash_update(ht, *str, var);
1899 				ZVAL_UNDEF(var);
1900 			}
1901 			str++;
1902 			var++;
1903 		} while (str != end);
1904 	}
1905 }
1906 /* }}} */
1907 
zend_set_local_var(zend_string * name,zval * value,bool force)1908 ZEND_API zend_result zend_set_local_var(zend_string *name, zval *value, bool force) /* {{{ */
1909 {
1910 	zend_execute_data *execute_data = EG(current_execute_data);
1911 
1912 	while (execute_data && (!execute_data->func || !ZEND_USER_CODE(execute_data->func->common.type))) {
1913 		execute_data = execute_data->prev_execute_data;
1914 	}
1915 
1916 	if (execute_data) {
1917 		if (!(EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE)) {
1918 			zend_ulong h = zend_string_hash_val(name);
1919 			zend_op_array *op_array = &execute_data->func->op_array;
1920 
1921 			if (EXPECTED(op_array->last_var)) {
1922 				zend_string **str = op_array->vars;
1923 				zend_string **end = str + op_array->last_var;
1924 
1925 				do {
1926 					if (ZSTR_H(*str) == h &&
1927 					    zend_string_equal_content(*str, name)) {
1928 						zval *var = EX_VAR_NUM(str - op_array->vars);
1929 						ZVAL_COPY_VALUE(var, value);
1930 						return SUCCESS;
1931 					}
1932 					str++;
1933 				} while (str != end);
1934 			}
1935 			if (force) {
1936 				zend_array *symbol_table = zend_rebuild_symbol_table();
1937 				if (symbol_table) {
1938 					zend_hash_update(symbol_table, name, value);
1939 					return SUCCESS;
1940 				}
1941 			}
1942 		} else {
1943 			zend_hash_update_ind(execute_data->symbol_table, name, value);
1944 			return SUCCESS;
1945 		}
1946 	}
1947 	return FAILURE;
1948 }
1949 /* }}} */
1950 
zend_set_local_var_str(const char * name,size_t len,zval * value,bool force)1951 ZEND_API zend_result zend_set_local_var_str(const char *name, size_t len, zval *value, bool force) /* {{{ */
1952 {
1953 	zend_execute_data *execute_data = EG(current_execute_data);
1954 
1955 	while (execute_data && (!execute_data->func || !ZEND_USER_CODE(execute_data->func->common.type))) {
1956 		execute_data = execute_data->prev_execute_data;
1957 	}
1958 
1959 	if (execute_data) {
1960 		if (!(EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE)) {
1961 			zend_ulong h = zend_hash_func(name, len);
1962 			zend_op_array *op_array = &execute_data->func->op_array;
1963 			if (EXPECTED(op_array->last_var)) {
1964 				zend_string **str = op_array->vars;
1965 				zend_string **end = str + op_array->last_var;
1966 
1967 				do {
1968 					if (ZSTR_H(*str) == h &&
1969 					    zend_string_equals_cstr(*str, name, len)) {
1970 						zval *var = EX_VAR_NUM(str - op_array->vars);
1971 						zval_ptr_dtor(var);
1972 						ZVAL_COPY_VALUE(var, value);
1973 						return SUCCESS;
1974 					}
1975 					str++;
1976 				} while (str != end);
1977 			}
1978 			if (force) {
1979 				zend_array *symbol_table = zend_rebuild_symbol_table();
1980 				if (symbol_table) {
1981 					zend_hash_str_update(symbol_table, name, len, value);
1982 					return SUCCESS;
1983 				}
1984 			}
1985 		} else {
1986 			zend_hash_str_update_ind(execute_data->symbol_table, name, len, value);
1987 			return SUCCESS;
1988 		}
1989 	}
1990 	return FAILURE;
1991 }
1992 /* }}} */
1993