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