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