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