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