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