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