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