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