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