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#define ZEND_INTENSIVE_DEBUGGING 0
23
24#include <stdio.h>
25#include <signal.h>
26
27#include "zend.h"
28#include "zend_compile.h"
29#include "zend_execute.h"
30#include "zend_API.h"
31#include "zend_ptr_stack.h"
32#include "zend_constants.h"
33#include "zend_extensions.h"
34#include "zend_ini.h"
35#include "zend_exceptions.h"
36#include "zend_interfaces.h"
37#include "zend_closures.h"
38#include "zend_generators.h"
39#include "zend_vm.h"
40#include "zend_dtrace.h"
41#include "zend_inheritance.h"
42
43/* Virtual current working directory support */
44#include "zend_virtual_cwd.h"
45
46#define _CONST_CODE  0
47#define _TMP_CODE    1
48#define _VAR_CODE    2
49#define _UNUSED_CODE 3
50#define _CV_CODE     4
51
52typedef int (*incdec_t)(zval *);
53
54#define get_zval_ptr(op_type, node, ex, should_free, type) _get_zval_ptr(op_type, node, ex, should_free, type TSRMLS_CC)
55#define get_zval_ptr_deref(op_type, node, ex, should_free, type) _get_zval_ptr_deref(op_type, node, ex, should_free, type TSRMLS_CC)
56#define get_zval_ptr_ptr(op_type, node, ex, should_free, type) _get_zval_ptr_ptr(op_type, node, ex, should_free, type TSRMLS_CC)
57#define get_zval_ptr_ptr_undef(op_type, node, ex, should_free, type) _get_zval_ptr_ptr(op_type, node, ex, should_free, type TSRMLS_CC)
58#define get_obj_zval_ptr(op_type, node, ex, should_free, type) _get_obj_zval_ptr(op_type, node, ex, should_free, type TSRMLS_CC)
59#define get_obj_zval_ptr_ptr(op_type, node, ex, should_free, type) _get_obj_zval_ptr_ptr(op_type, node, ex, should_free, type TSRMLS_CC)
60
61/* Prototypes */
62static void zend_extension_statement_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC);
63static void zend_extension_fcall_begin_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC);
64static void zend_extension_fcall_end_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC);
65
66#define RETURN_VALUE_USED(opline) (!((opline)->result_type & EXT_TYPE_UNUSED))
67
68static ZEND_FUNCTION(pass)
69{
70}
71
72static const zend_internal_function zend_pass_function = {
73    ZEND_INTERNAL_FUNCTION, /* type              */
74    0,                      /* fn_flags          */
75    NULL,                   /* name              */
76    NULL,                   /* scope             */
77    NULL,                   /* prototype         */
78    0,                      /* num_args          */
79    0,                      /* required_num_args */
80    NULL,                   /* arg_info          */
81    ZEND_FN(pass),          /* handler           */
82    NULL                    /* module            */
83};
84
85#undef zval_ptr_dtor
86#define zval_ptr_dtor(zv) i_zval_ptr_dtor(zv ZEND_FILE_LINE_CC TSRMLS_CC)
87
88#define PZVAL_LOCK(z) if (Z_REFCOUNTED_P(z)) Z_ADDREF_P((z))
89#define SELECTIVE_PZVAL_LOCK(pzv, opline)   if (RETURN_VALUE_USED(opline)) { PZVAL_LOCK(pzv); }
90
91#define READY_TO_DESTROY(zv) \
92    (zv && Z_REFCOUNTED_P(zv) && Z_REFCOUNT_P(zv) == 1)
93
94#define EXTRACT_ZVAL_PTR(zv) do {                       \
95        zval *__zv = (zv);                              \
96        if (Z_TYPE_P(__zv) == IS_INDIRECT) {            \
97            ZVAL_COPY(__zv, Z_INDIRECT_P(__zv));        \
98        }                                               \
99    } while (0)
100
101#define FREE_OP(should_free) \
102    if (should_free.var) { \
103        zval_ptr_dtor_nogc(should_free.var); \
104    }
105
106#define FREE_OP_VAR_PTR(should_free) \
107    if (should_free.var) { \
108        zval_ptr_dtor_nogc(should_free.var); \
109    }
110
111/* End of zend_execute_locks.h */
112
113#define CV_DEF_OF(i) (EX(func)->op_array.vars[i])
114
115#define CTOR_CALL_BIT    0x1
116#define CTOR_USED_BIT    0x2
117
118#define IS_CTOR_CALL(ce) (((zend_uintptr_t)(ce)) & CTOR_CALL_BIT)
119#define IS_CTOR_USED(ce) (((zend_uintptr_t)(ce)) & CTOR_USED_BIT)
120
121#define ENCODE_CTOR(ce, used) \
122    ((zend_class_entry*)(((zend_uintptr_t)(ce)) | CTOR_CALL_BIT | ((used) ? CTOR_USED_BIT : 0)))
123#define DECODE_CTOR(ce) \
124    ((zend_class_entry*)(((zend_uintptr_t)(ce)) & ~(CTOR_CALL_BIT|CTOR_USED_BIT)))
125
126#define ZEND_VM_STACK_PAGE_SLOTS (16 * 1024) /* should be a power of 2 */
127
128#define ZEND_VM_STACK_PAGE_SIZE  (ZEND_VM_STACK_PAGE_SLOTS * sizeof(zval))
129
130#define ZEND_VM_STACK_FREE_PAGE_SIZE \
131    ((ZEND_VM_STACK_PAGE_SLOTS - ZEND_VM_STACK_HEADER_SLOTS) * sizeof(zval))
132
133#define ZEND_VM_STACK_PAGE_ALIGNED_SIZE(size) \
134    (((size) + (ZEND_VM_STACK_FREE_PAGE_SIZE - 1)) & ~ZEND_VM_STACK_PAGE_SIZE)
135
136static zend_always_inline zend_vm_stack zend_vm_stack_new_page(size_t size, zend_vm_stack prev) {
137    zend_vm_stack page = (zend_vm_stack)emalloc(size);
138
139    page->top = ZEND_VM_STACK_ELEMETS(page);
140    page->end = (zval*)((char*)page + size);
141    page->prev = prev;
142    return page;
143}
144
145ZEND_API void zend_vm_stack_init(TSRMLS_D)
146{
147    EG(vm_stack) = zend_vm_stack_new_page(ZEND_VM_STACK_PAGE_SIZE, NULL);
148    EG(vm_stack)->top++;
149    EG(vm_stack_top) = EG(vm_stack)->top;
150    EG(vm_stack_end) = EG(vm_stack)->end;
151}
152
153ZEND_API void zend_vm_stack_destroy(TSRMLS_D)
154{
155    zend_vm_stack stack = EG(vm_stack);
156
157    while (stack != NULL) {
158        zend_vm_stack p = stack->prev;
159        efree(stack);
160        stack = p;
161    }
162}
163
164ZEND_API void* zend_vm_stack_extend(size_t size TSRMLS_DC)
165{
166    zend_vm_stack stack;
167    void *ptr;
168
169    stack = EG(vm_stack);
170    stack->top = EG(vm_stack_top);
171    EG(vm_stack) = stack = zend_vm_stack_new_page(
172        EXPECTED(size < ZEND_VM_STACK_FREE_PAGE_SIZE) ?
173            ZEND_VM_STACK_PAGE_SIZE : ZEND_VM_STACK_PAGE_ALIGNED_SIZE(size),
174        stack);
175    ptr = stack->top;
176    EG(vm_stack_top) = (void*)(((char*)ptr) + size);
177    EG(vm_stack_end) = stack->end;
178    return ptr;
179}
180
181ZEND_API zval* zend_get_compiled_variable_value(const zend_execute_data *execute_data, uint32_t var)
182{
183    return EX_VAR(var);
184}
185
186static zend_always_inline zval *_get_zval_ptr_tmp(uint32_t var, const zend_execute_data *execute_data, zend_free_op *should_free TSRMLS_DC)
187{
188    zval *ret = EX_VAR(var);
189    should_free->var = ret;
190
191    ZEND_ASSERT(Z_TYPE_P(ret) != IS_REFERENCE);
192
193    return ret;
194}
195
196static zend_always_inline zval *_get_zval_ptr_var(uint32_t var, const zend_execute_data *execute_data, zend_free_op *should_free TSRMLS_DC)
197{
198    zval *ret = EX_VAR(var);
199
200    should_free->var = ret;
201    return ret;
202}
203
204static zend_always_inline zval *_get_zval_ptr_var_deref(uint32_t var, const zend_execute_data *execute_data, zend_free_op *should_free TSRMLS_DC)
205{
206    zval *ret = EX_VAR(var);
207
208    should_free->var = ret;
209    ZVAL_DEREF(ret);
210    return ret;
211}
212
213static zend_never_inline zval *_get_zval_cv_lookup(zval *ptr, uint32_t var, int type, const zend_execute_data *execute_data TSRMLS_DC)
214{
215    zend_string *cv;
216
217    switch (type) {
218        case BP_VAR_R:
219        case BP_VAR_UNSET:
220            cv = CV_DEF_OF(EX_VAR_TO_NUM(var));
221            zend_error(E_NOTICE, "Undefined variable: %s", cv->val);
222            /* break missing intentionally */
223        case BP_VAR_IS:
224            ptr = &EG(uninitialized_zval);
225            break;
226        case BP_VAR_RW:
227            cv = CV_DEF_OF(EX_VAR_TO_NUM(var));
228            zend_error(E_NOTICE, "Undefined variable: %s", cv->val);
229            /* break missing intentionally */
230        case BP_VAR_W:
231            ZVAL_NULL(ptr);
232            break;
233    }
234    return ptr;
235}
236
237static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_R(zval *ptr, uint32_t var, const zend_execute_data *execute_data TSRMLS_DC)
238{
239    zend_string *cv = CV_DEF_OF(EX_VAR_TO_NUM(var));
240
241    zend_error(E_NOTICE, "Undefined variable: %s", cv->val);
242    return &EG(uninitialized_zval);
243}
244
245static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_UNSET(zval *ptr, uint32_t var, const zend_execute_data *execute_data TSRMLS_DC)
246{
247    zend_string *cv = CV_DEF_OF(EX_VAR_TO_NUM(var));
248
249    zend_error(E_NOTICE, "Undefined variable: %s", cv->val);
250    return &EG(uninitialized_zval);
251}
252
253static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_RW(zval *ptr, uint32_t var, const zend_execute_data *execute_data TSRMLS_DC)
254{
255    zend_string *cv = CV_DEF_OF(EX_VAR_TO_NUM(var));
256
257    ZVAL_NULL(ptr);
258    zend_error(E_NOTICE, "Undefined variable: %s", cv->val);
259    return ptr;
260}
261
262static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_W(zval *ptr, uint32_t var, const zend_execute_data *execute_data TSRMLS_DC)
263{
264    ZVAL_NULL(ptr);
265    return ptr;
266}
267
268static zend_always_inline zval *_get_zval_ptr_cv(const zend_execute_data *execute_data, uint32_t var, int type TSRMLS_DC)
269{
270    zval *ret = EX_VAR(var);
271
272    if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
273        return _get_zval_cv_lookup(ret, var, type, execute_data TSRMLS_CC);
274    }
275    return ret;
276}
277
278static zend_always_inline zval *_get_zval_ptr_cv_deref(const zend_execute_data *execute_data, uint32_t var, int type TSRMLS_DC)
279{
280    zval *ret = EX_VAR(var);
281
282    if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
283        return _get_zval_cv_lookup(ret, var, type, execute_data TSRMLS_CC);
284    }
285    ZVAL_DEREF(ret);
286    return ret;
287}
288
289static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_R(const zend_execute_data *execute_data, uint32_t var TSRMLS_DC)
290{
291    zval *ret = EX_VAR(var);
292
293    if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
294        return _get_zval_cv_lookup_BP_VAR_R(ret, var, execute_data TSRMLS_CC);
295    }
296    return ret;
297}
298
299static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_R(const zend_execute_data *execute_data, uint32_t var TSRMLS_DC)
300{
301    zval *ret = EX_VAR(var);
302
303    if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
304        return _get_zval_cv_lookup_BP_VAR_R(ret, var, execute_data TSRMLS_CC);
305    }
306    ZVAL_DEREF(ret);
307    return ret;
308}
309
310static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_UNSET(const zend_execute_data *execute_data, uint32_t var TSRMLS_DC)
311{
312    zval *ret = EX_VAR(var);
313
314    if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
315        return _get_zval_cv_lookup_BP_VAR_UNSET(ret, var, execute_data TSRMLS_CC);
316    }
317    return ret;
318}
319
320static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_UNSET(const zend_execute_data *execute_data, uint32_t var TSRMLS_DC)
321{
322    zval *ret = EX_VAR(var);
323
324    if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
325        return _get_zval_cv_lookup_BP_VAR_UNSET(ret, var, execute_data TSRMLS_CC);
326    }
327    ZVAL_DEREF(ret);
328    return ret;
329}
330
331static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_IS(const zend_execute_data *execute_data, uint32_t var TSRMLS_DC)
332{
333    zval *ret = EX_VAR(var);
334
335    return ret;
336}
337
338static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_IS(const zend_execute_data *execute_data, uint32_t var TSRMLS_DC)
339{
340    zval *ret = EX_VAR(var);
341
342    ZVAL_DEREF(ret);
343    return ret;
344}
345
346static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_RW(const zend_execute_data *execute_data, uint32_t var TSRMLS_DC)
347{
348    zval *ret = EX_VAR(var);
349
350    if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
351        return _get_zval_cv_lookup_BP_VAR_RW(ret, var, execute_data TSRMLS_CC);
352    }
353    return ret;
354}
355
356static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_RW(const zend_execute_data *execute_data, uint32_t var TSRMLS_DC)
357{
358    zval *ret = EX_VAR(var);
359
360    if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
361        return _get_zval_cv_lookup_BP_VAR_RW(ret, var, execute_data TSRMLS_CC);
362    }
363    ZVAL_DEREF(ret);
364    return ret;
365}
366
367static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_W(const zend_execute_data *execute_data, uint32_t var TSRMLS_DC)
368{
369    zval *ret = EX_VAR(var);
370
371    if (Z_TYPE_P(ret) == IS_UNDEF) {
372        return _get_zval_cv_lookup_BP_VAR_W(ret, var, execute_data TSRMLS_CC);
373    }
374    return ret;
375}
376
377static zend_always_inline zval *_get_zval_ptr_cv_undef_BP_VAR_W(const zend_execute_data *execute_data, uint32_t var TSRMLS_DC)
378{
379    return EX_VAR(var);
380}
381
382static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_W(const zend_execute_data *execute_data, uint32_t var TSRMLS_DC)
383{
384    zval *ret = EX_VAR(var);
385
386    if (Z_TYPE_P(ret) == IS_UNDEF) {
387        return _get_zval_cv_lookup_BP_VAR_W(ret, var, execute_data TSRMLS_CC);
388    }
389    ZVAL_DEREF(ret);
390    return ret;
391}
392
393static inline zval *_get_zval_ptr(int op_type, const znode_op *node, const zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC)
394{
395    zval *ret;
396
397    switch (op_type) {
398        case IS_CONST:
399            should_free->var = NULL;
400            return node->zv;
401            break;
402        case IS_TMP_VAR:
403            ret = EX_VAR(node->var);
404            should_free->var = ret;
405            return ret;
406            break;
407        case IS_VAR:
408            return _get_zval_ptr_var(node->var, execute_data, should_free TSRMLS_CC);
409            break;
410        case IS_UNUSED:
411            should_free->var = NULL;
412            return NULL;
413            break;
414        case IS_CV:
415        default:
416            should_free->var = NULL;
417            return _get_zval_ptr_cv(execute_data, node->var, type TSRMLS_CC);
418            break;
419    }
420    return NULL;
421}
422
423static inline zval *_get_zval_ptr_deref(int op_type, const znode_op *node, const zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC)
424{
425    zval *ret;
426
427    switch (op_type) {
428        case IS_CONST:
429            should_free->var = NULL;
430            return node->zv;
431            break;
432        case IS_TMP_VAR:
433            ret = EX_VAR(node->var);
434            should_free->var = ret;
435            return ret;
436            break;
437        case IS_VAR:
438            return _get_zval_ptr_var_deref(node->var, execute_data, should_free TSRMLS_CC);
439            break;
440        case IS_UNUSED:
441            should_free->var = NULL;
442            return NULL;
443            break;
444        case IS_CV:
445        default:
446            should_free->var = NULL;
447            return _get_zval_ptr_cv_deref(execute_data, node->var, type TSRMLS_CC);
448            break;
449    }
450    return NULL;
451}
452
453static zend_always_inline zval *_get_zval_ptr_ptr_var(uint32_t var, const zend_execute_data *execute_data, zend_free_op *should_free TSRMLS_DC)
454{
455    zval *ret = EX_VAR(var);
456
457    if (EXPECTED(Z_TYPE_P(ret) == IS_INDIRECT)) {
458        should_free->var = NULL;
459        return Z_INDIRECT_P(ret);
460    } else if (!Z_REFCOUNTED_P(ret) || Z_REFCOUNT_P(ret) == 1) {
461        should_free->var = ret;
462        return ret;
463    } else {
464        Z_DELREF_P(ret);
465        should_free->var = NULL;
466        return ret;
467    }
468}
469
470static inline zval *_get_zval_ptr_ptr(int op_type, const znode_op *node, const zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC)
471{
472    if (op_type == IS_CV) {
473        should_free->var = NULL;
474        return _get_zval_ptr_cv(execute_data, node->var, type TSRMLS_CC);
475    } else /* if (op_type == IS_VAR) */ {
476        ZEND_ASSERT(op_type == IS_VAR);
477        return _get_zval_ptr_ptr_var(node->var, execute_data, should_free TSRMLS_CC);
478    }
479}
480
481static zend_always_inline zval *_get_obj_zval_ptr_unused(zend_execute_data *execute_data TSRMLS_DC)
482{
483    if (EXPECTED(Z_OBJ(EX(This)) != NULL)) {
484        return &EX(This);
485    } else {
486        zend_error_noreturn(E_ERROR, "Using $this when not in object context");
487        return NULL;
488    }
489}
490
491static inline zval *_get_obj_zval_ptr(int op_type, znode_op *op, zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC)
492{
493    if (op_type == IS_UNUSED) {
494        if (EXPECTED(Z_OBJ(EX(This)) != NULL)) {
495            should_free->var = NULL;
496            return &EX(This);
497        } else {
498            zend_error_noreturn(E_ERROR, "Using $this when not in object context");
499        }
500    }
501    return get_zval_ptr(op_type, op, execute_data, should_free, type);
502}
503
504static inline zval *_get_obj_zval_ptr_ptr(int op_type, const znode_op *node, zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC)
505{
506    if (op_type == IS_UNUSED) {
507        if (EXPECTED(Z_OBJ(EX(This)) != NULL)) {
508            should_free->var = NULL;
509            return &EX(This);
510        } else {
511            zend_error_noreturn(E_ERROR, "Using $this when not in object context");
512        }
513    }
514    return get_zval_ptr_ptr(op_type, node, execute_data, should_free, type);
515}
516
517static inline void zend_assign_to_variable_reference(zval *variable_ptr, zval *value_ptr TSRMLS_DC)
518{
519    if (EXPECTED(variable_ptr != value_ptr)) {
520        zend_reference *ref;
521        ZVAL_MAKE_REF(value_ptr);
522        Z_ADDREF_P(value_ptr);
523        ref = Z_REF_P(value_ptr);
524
525        zval_ptr_dtor(variable_ptr);
526        ZVAL_REF(variable_ptr, ref);
527    } else {
528        ZVAL_MAKE_REF(variable_ptr);
529    }
530}
531
532/* this should modify object only if it's empty */
533static inline zval* make_real_object(zval *object_ptr TSRMLS_DC)
534{
535    zval *object = object_ptr;
536
537    ZVAL_DEREF(object);
538    if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
539        if (Z_TYPE_P(object) == IS_NULL
540            || Z_TYPE_P(object) == IS_FALSE
541            || (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0)) {
542            zval_ptr_dtor_nogc(object);
543            object_init(object);
544            zend_error(E_WARNING, "Creating default object from empty value");
545        }
546    }
547    return object;
548}
549
550ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, char **class_name, zend_class_entry **pce TSRMLS_DC)
551{
552    zend_string *key;
553    ALLOCA_FLAG(use_heap);
554
555    STR_ALLOCA_INIT(key, cur_arg_info->class_name, cur_arg_info->class_name_len, use_heap);
556    *pce = zend_fetch_class(key, (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD) TSRMLS_CC);
557    STR_ALLOCA_FREE(key, use_heap);
558
559    *class_name = (*pce) ? (*pce)->name->val : (char*)cur_arg_info->class_name;
560    if (*pce && (*pce)->ce_flags & ZEND_ACC_INTERFACE) {
561        return "implement interface ";
562    } else {
563        return "be an instance of ";
564    }
565}
566
567ZEND_API void zend_verify_arg_error(int error_type, const zend_function *zf, uint32_t arg_num, const char *need_msg, const char *need_kind, const char *given_msg, const char *given_kind, zval *arg TSRMLS_DC)
568{
569    zend_execute_data *ptr = EG(current_execute_data)->prev_execute_data;
570    const char *fname = zf->common.function_name->val;
571    const char *fsep;
572    const char *fclass;
573    zval old_arg;
574
575    if (zf->common.scope) {
576        fsep =  "::";
577        fclass = zf->common.scope->name->val;
578    } else {
579        fsep =  "";
580        fclass = "";
581    }
582
583    if (arg && zf->common.type == ZEND_USER_FUNCTION) {
584        ZVAL_COPY_VALUE(&old_arg, arg);
585        ZVAL_UNDEF(arg);
586    }
587
588    if (zf->common.type == ZEND_USER_FUNCTION && ptr && ptr->func && ZEND_USER_CODE(ptr->func->common.type)) {
589        zend_error(error_type, "Argument %d passed to %s%s%s() must %s%s, %s%s given, called in %s on line %d and defined", arg_num, fclass, fsep, fname, need_msg, need_kind, given_msg, given_kind, ptr->func->op_array.filename->val, ptr->opline->lineno);
590    } else {
591        zend_error(error_type, "Argument %d passed to %s%s%s() must %s%s, %s%s given", arg_num, fclass, fsep, fname, need_msg, need_kind, given_msg, given_kind);
592    }
593
594    if (arg && zf->common.type == ZEND_USER_FUNCTION) {
595        ZVAL_COPY_VALUE(arg, &old_arg);
596    }
597}
598
599static void zend_verify_arg_type(zend_function *zf, uint32_t arg_num, zval *arg TSRMLS_DC)
600{
601    zend_arg_info *cur_arg_info;
602    char *need_msg;
603    zend_class_entry *ce;
604
605    if (UNEXPECTED(!zf->common.arg_info)) {
606        return;
607    }
608
609    if (EXPECTED(arg_num <= zf->common.num_args)) {
610        cur_arg_info = &zf->common.arg_info[arg_num-1];
611    } else if (zf->common.fn_flags & ZEND_ACC_VARIADIC) {
612        cur_arg_info = &zf->common.arg_info[zf->common.num_args-1];
613    } else {
614        return;
615    }
616
617    if (cur_arg_info->class_name) {
618        char *class_name;
619
620        ZVAL_DEREF(arg);
621        if (Z_TYPE_P(arg) == IS_OBJECT) {
622            need_msg = zend_verify_arg_class_kind(cur_arg_info, &class_name, &ce TSRMLS_CC);
623            if (!ce || !instanceof_function(Z_OBJCE_P(arg), ce TSRMLS_CC)) {
624                zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, "instance of ", Z_OBJCE_P(arg)->name->val, arg TSRMLS_CC);
625            }
626        } else if (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null) {
627            need_msg = zend_verify_arg_class_kind(cur_arg_info, &class_name, &ce TSRMLS_CC);
628            zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, zend_zval_type_name(arg), "", arg TSRMLS_CC);
629        }
630    } else if (cur_arg_info->type_hint) {
631        if (cur_arg_info->type_hint == IS_ARRAY) {
632            ZVAL_DEREF(arg);
633            if (Z_TYPE_P(arg) != IS_ARRAY && (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null)) {
634                zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be of the type array", "", zend_zval_type_name(arg), "", arg TSRMLS_CC);
635            }
636        } else if (cur_arg_info->type_hint == IS_CALLABLE) {
637            if (!zend_is_callable(arg, IS_CALLABLE_CHECK_SILENT, NULL TSRMLS_CC) && (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null)) {
638                zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be callable", "", zend_zval_type_name(arg), "", arg TSRMLS_CC);
639            }
640#if ZEND_DEBUG
641        } else {
642            zend_error(E_ERROR, "Unknown typehint");
643#endif
644        }
645    }
646}
647
648static inline int zend_verify_missing_arg_type(zend_function *zf, uint32_t arg_num TSRMLS_DC)
649{
650    zend_arg_info *cur_arg_info;
651    char *need_msg;
652    zend_class_entry *ce;
653
654    if (UNEXPECTED(!zf->common.arg_info)) {
655        return 1;
656    }
657
658    if (EXPECTED(arg_num <= zf->common.num_args)) {
659        cur_arg_info = &zf->common.arg_info[arg_num-1];
660    } else if (zf->common.fn_flags & ZEND_ACC_VARIADIC) {
661        cur_arg_info = &zf->common.arg_info[zf->common.num_args-1];
662    } else {
663        return 1;
664    }
665
666    if (cur_arg_info->class_name) {
667        char *class_name;
668
669        need_msg = zend_verify_arg_class_kind(cur_arg_info, &class_name, &ce TSRMLS_CC);
670        zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, "none", "", NULL TSRMLS_CC);
671        return 0;
672    } else if (cur_arg_info->type_hint) {
673        if (cur_arg_info->type_hint == IS_ARRAY) {
674            zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be of the type array", "", "none", "", NULL TSRMLS_CC);
675        } else if (cur_arg_info->type_hint == IS_CALLABLE) {
676            zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be callable", "", "none", "", NULL TSRMLS_CC);
677#if ZEND_DEBUG
678        } else {
679            zend_error(E_ERROR, "Unknown typehint");
680#endif
681        }
682        return 0;
683    }
684    return 1;
685}
686
687static void zend_verify_missing_arg(zend_execute_data *execute_data, uint32_t arg_num TSRMLS_DC)
688{
689    if (EXPECTED(!(EX(func)->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS)) ||
690        zend_verify_missing_arg_type(EX(func), arg_num TSRMLS_CC)) {
691        const char *class_name = EX(func)->common.scope ? EX(func)->common.scope->name->val : "";
692        const char *space = EX(func)->common.scope ? "::" : "";
693        const char *func_name = EX(func)->common.function_name ? EX(func)->common.function_name->val : "main";
694        zend_execute_data *ptr = EX(prev_execute_data);
695
696        if (ptr && ptr->func && ZEND_USER_CODE(ptr->func->common.type)) {
697            zend_error(E_WARNING, "Missing argument %u for %s%s%s(), called in %s on line %d and defined", arg_num, class_name, space, func_name, ptr->func->op_array.filename->val, ptr->opline->lineno);
698        } else {
699            zend_error(E_WARNING, "Missing argument %u for %s%s%s()", arg_num, class_name, space, func_name);
700        }
701    }
702}
703
704static zend_always_inline void zend_assign_to_object(zval *retval, zval *object, uint32_t object_op_type, zval *property_name, int value_type, const znode_op *value_op, const zend_execute_data *execute_data, int opcode, void **cache_slot TSRMLS_DC)
705{
706    zend_free_op free_value;
707    zval *value = get_zval_ptr(value_type, value_op, execute_data, &free_value, BP_VAR_R);
708    zval tmp;
709
710    if (object_op_type != IS_UNUSED) {
711        ZVAL_DEREF(object);
712        if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
713            if (UNEXPECTED(object == &EG(error_zval))) {
714                if (retval) {
715                    ZVAL_NULL(retval);
716                }
717                FREE_OP(free_value);
718                return;
719            }
720            if (EXPECTED(Z_TYPE_P(object) == IS_NULL ||
721                Z_TYPE_P(object) == IS_FALSE ||
722                (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) {
723                zend_object *obj;
724
725                zval_ptr_dtor(object);
726                object_init(object);
727                Z_ADDREF_P(object);
728                obj = Z_OBJ_P(object);
729                zend_error(E_WARNING, "Creating default object from empty value");
730                if (GC_REFCOUNT(obj) == 1) {
731                    /* the enclosing container was deleted, obj is unreferenced */
732                    if (retval) {
733                        ZVAL_NULL(retval);
734                    }
735                    FREE_OP(free_value);
736                    OBJ_RELEASE(obj);
737                    return;
738                }
739                Z_DELREF_P(object);
740            } else {
741                zend_error(E_WARNING, "Attempt to assign property of non-object");
742                if (retval) {
743                    ZVAL_NULL(retval);
744                }
745                FREE_OP(free_value);
746                return;
747            }
748        }
749    }
750
751    /* separate our value if necessary */
752    if (value_type == IS_TMP_VAR) {
753        ZVAL_COPY_VALUE(&tmp, value);
754        value = &tmp;
755    } else if (value_type == IS_CONST) {
756        if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
757            ZVAL_COPY_VALUE(&tmp, value);
758            zval_copy_ctor_func(&tmp);
759            value = &tmp;
760        }
761    } else if (Z_REFCOUNTED_P(value)) {
762        Z_ADDREF_P(value);
763    }
764
765    if (opcode == ZEND_ASSIGN_OBJ) {
766        if (!Z_OBJ_HT_P(object)->write_property) {
767            zend_error(E_WARNING, "Attempt to assign property of non-object");
768            if (retval) {
769                ZVAL_NULL(retval);
770            }
771            if (value_type == IS_CONST) {
772                zval_ptr_dtor(value);
773            }
774            FREE_OP(free_value);
775            return;
776        }
777        Z_OBJ_HT_P(object)->write_property(object, property_name, value, cache_slot TSRMLS_CC);
778    } else {
779        /* Note:  property_name in this case is really the array index! */
780        if (!Z_OBJ_HT_P(object)->write_dimension) {
781            zend_error_noreturn(E_ERROR, "Cannot use object as array");
782        }
783        Z_OBJ_HT_P(object)->write_dimension(object, property_name, value TSRMLS_CC);
784    }
785
786    if (retval && !EG(exception)) {
787        ZVAL_COPY(retval, value);
788    }
789    zval_ptr_dtor(value);
790    if (value_type == IS_VAR) {
791        FREE_OP(free_value);
792    }
793}
794
795static void zend_assign_to_string_offset(zval *str, zend_long offset, zval *value, zval *result TSRMLS_DC)
796{
797    zend_string *old_str;
798
799    if (offset < 0) {
800        zend_error(E_WARNING, "Illegal string offset:  " ZEND_LONG_FMT, offset);
801        zend_string_release(Z_STR_P(str));
802        if (result) {
803            ZVAL_NULL(result);
804        }
805        return;
806    }
807
808    old_str = Z_STR_P(str);
809    if ((size_t)offset >= Z_STRLEN_P(str)) {
810        zend_long old_len = Z_STRLEN_P(str);
811        Z_STR_P(str) = zend_string_realloc(Z_STR_P(str), offset + 1, 0);
812        Z_TYPE_INFO_P(str) = IS_STRING_EX;
813        memset(Z_STRVAL_P(str) + old_len, ' ', offset - old_len);
814        Z_STRVAL_P(str)[offset+1] = 0;
815    } else if (!Z_REFCOUNTED_P(str)) {
816        Z_STR_P(str) = zend_string_init(Z_STRVAL_P(str), Z_STRLEN_P(str), 0);
817        Z_TYPE_INFO_P(str) = IS_STRING_EX;
818    }
819
820    if (Z_TYPE_P(value) != IS_STRING) {
821        zend_string *tmp = zval_get_string(value);
822
823        Z_STRVAL_P(str)[offset] = tmp->val[0];
824        zend_string_release(tmp);
825    } else {
826        Z_STRVAL_P(str)[offset] = Z_STRVAL_P(value)[0];
827    }
828    /*
829     * the value of an assignment to a string offset is undefined
830    T(result->u.var).var = &T->str_offset.str;
831    */
832
833    zend_string_release(old_str);
834    if (result) {
835        zend_uchar c = (zend_uchar)Z_STRVAL_P(str)[offset];
836
837        if (CG(one_char_string)[c]) {
838            ZVAL_INTERNED_STR(result, CG(one_char_string)[c]);
839        } else {
840            ZVAL_NEW_STR(result, zend_string_init(Z_STRVAL_P(str) + offset, 1, 0));
841        }
842    }
843}
844
845static zend_always_inline zval* zend_assign_to_variable(zval *variable_ptr, zval *value, zend_uchar value_type TSRMLS_DC)
846{
847    do {
848        if (UNEXPECTED(Z_REFCOUNTED_P(variable_ptr))) {
849            zend_refcounted *garbage;
850
851            if (Z_ISREF_P(variable_ptr)) {
852                variable_ptr = Z_REFVAL_P(variable_ptr);
853                if (EXPECTED(!Z_REFCOUNTED_P(variable_ptr))) {
854                    break;
855                }
856            }
857            if (Z_TYPE_P(variable_ptr) == IS_OBJECT &&
858                UNEXPECTED(Z_OBJ_HANDLER_P(variable_ptr, set) != NULL)) {
859                Z_OBJ_HANDLER_P(variable_ptr, set)(variable_ptr, value TSRMLS_CC);
860                return variable_ptr;
861            }
862            if ((value_type & (IS_VAR|IS_CV)) && variable_ptr == value) {
863                return variable_ptr;
864            }
865            garbage = Z_COUNTED_P(variable_ptr);
866            if (--GC_REFCOUNT(garbage) == 0) {
867                ZVAL_COPY_VALUE(variable_ptr, value);
868                if (value_type == IS_CONST) {
869                    /* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */
870                    if (UNEXPECTED(Z_OPT_COPYABLE_P(variable_ptr))) {
871                        zval_copy_ctor_func(variable_ptr);
872                    }
873                } else if (value_type != IS_TMP_VAR) {
874                    if (UNEXPECTED(Z_OPT_REFCOUNTED_P(variable_ptr))) {
875                        Z_ADDREF_P(variable_ptr);
876                    }
877                }
878                _zval_dtor_func_for_ptr(garbage ZEND_FILE_LINE_CC);
879                return variable_ptr;
880            } else { /* we need to split */
881                /* optimized version of GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr) */
882                if ((Z_COLLECTABLE_P(variable_ptr)) &&
883                    UNEXPECTED(!GC_INFO(garbage))) {
884                    gc_possible_root(garbage TSRMLS_CC);
885                }
886            }
887        }
888    } while (0);
889
890    ZVAL_COPY_VALUE(variable_ptr, value);
891    if (value_type == IS_CONST) {
892        /* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */
893        if (UNEXPECTED(Z_OPT_COPYABLE_P(variable_ptr))) {
894            zval_copy_ctor_func(variable_ptr);
895        }
896    } else if (value_type != IS_TMP_VAR) {
897        if (UNEXPECTED(Z_OPT_REFCOUNTED_P(variable_ptr))) {
898            Z_ADDREF_P(variable_ptr);
899        }
900    }
901    return variable_ptr;
902}
903
904/* Utility Functions for Extensions */
905static void zend_extension_statement_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC)
906{
907    if (extension->statement_handler) {
908        extension->statement_handler(op_array);
909    }
910}
911
912
913static void zend_extension_fcall_begin_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC)
914{
915    if (extension->fcall_begin_handler) {
916        extension->fcall_begin_handler(op_array);
917    }
918}
919
920
921static void zend_extension_fcall_end_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC)
922{
923    if (extension->fcall_end_handler) {
924        extension->fcall_end_handler(op_array);
925    }
926}
927
928
929static zend_always_inline HashTable *zend_get_target_symbol_table(zend_execute_data *execute_data, int fetch_type TSRMLS_DC)
930{
931    HashTable *ht;
932
933    if (EXPECTED(fetch_type == ZEND_FETCH_GLOBAL_LOCK) ||
934        EXPECTED(fetch_type == ZEND_FETCH_GLOBAL)) {
935        ht = &EG(symbol_table).ht;
936    } else if (EXPECTED(fetch_type == ZEND_FETCH_STATIC)) {
937        ZEND_ASSERT(EX(func)->op_array.static_variables != NULL);
938        ht = EX(func)->op_array.static_variables;
939    } else {
940        ZEND_ASSERT(fetch_type == ZEND_FETCH_LOCAL);
941        if (!EX(symbol_table)) {
942            zend_rebuild_symbol_table(TSRMLS_C);
943        }
944        ht = &EX(symbol_table)->ht;
945    }
946    return ht;
947}
948
949static zend_always_inline zval *zend_fetch_dimension_address_inner(HashTable *ht, const zval *dim, int dim_type, int type TSRMLS_DC)
950{
951    zval *retval;
952    zend_string *offset_key;
953    zend_ulong hval;
954
955    if (EXPECTED(Z_TYPE_P(dim) == IS_LONG)) {
956        hval = Z_LVAL_P(dim);
957num_index:
958        retval = zend_hash_index_find(ht, hval);
959        if (retval == NULL) {
960            switch (type) {
961                case BP_VAR_R:
962                    zend_error(E_NOTICE,"Undefined offset: " ZEND_ULONG_FMT, hval);
963                    /* break missing intentionally */
964                case BP_VAR_UNSET:
965                case BP_VAR_IS:
966                    retval = &EG(uninitialized_zval);
967                    break;
968                case BP_VAR_RW:
969                    zend_error(E_NOTICE,"Undefined offset: " ZEND_ULONG_FMT, hval);
970                    /* break missing intentionally */
971                case BP_VAR_W:
972                    retval = zend_hash_index_add_new(ht, hval, &EG(uninitialized_zval));
973                    break;
974            }
975        }
976    } else if (EXPECTED(Z_TYPE_P(dim) == IS_STRING)) {
977        offset_key = Z_STR_P(dim);
978        if (dim_type != IS_CONST) {
979            if (ZEND_HANDLE_NUMERIC(offset_key, hval)) {
980                goto num_index;
981            }
982        }
983str_index:
984        retval = zend_hash_find(ht, offset_key);
985        if (retval) {
986            /* support for $GLOBALS[...] */
987            if (UNEXPECTED(Z_TYPE_P(retval) == IS_INDIRECT)) {
988                retval = Z_INDIRECT_P(retval);
989                if (UNEXPECTED(Z_TYPE_P(retval) == IS_UNDEF)) {
990                    switch (type) {
991                        case BP_VAR_R:
992                            zend_error(E_NOTICE, "Undefined index: %s", offset_key->val);
993                            /* break missing intentionally */
994                        case BP_VAR_UNSET:
995                        case BP_VAR_IS:
996                            retval = &EG(uninitialized_zval);
997                            break;
998                        case BP_VAR_RW:
999                            zend_error(E_NOTICE,"Undefined index: %s", offset_key->val);
1000                            /* break missing intentionally */
1001                        case BP_VAR_W:
1002                            ZVAL_NULL(retval);
1003                            break;
1004                    }
1005                }
1006            }
1007        } else {
1008            switch (type) {
1009                case BP_VAR_R:
1010                    zend_error(E_NOTICE, "Undefined index: %s", offset_key->val);
1011                    /* break missing intentionally */
1012                case BP_VAR_UNSET:
1013                case BP_VAR_IS:
1014                    retval = &EG(uninitialized_zval);
1015                    break;
1016                case BP_VAR_RW:
1017                    zend_error(E_NOTICE,"Undefined index: %s", offset_key->val);
1018                    /* break missing intentionally */
1019                case BP_VAR_W:
1020                    retval = zend_hash_add_new(ht, offset_key, &EG(uninitialized_zval));
1021                    break;
1022            }
1023        }
1024    } else {
1025        switch (Z_TYPE_P(dim)) {
1026            case IS_NULL:
1027                offset_key = STR_EMPTY_ALLOC();
1028                goto str_index;
1029            case IS_DOUBLE:
1030                hval = zend_dval_to_lval(Z_DVAL_P(dim));
1031                goto num_index;
1032            case IS_RESOURCE:
1033                zend_error(E_STRICT, "Resource ID#%pd used as offset, casting to integer (%pd)", Z_RES_HANDLE_P(dim), Z_RES_HANDLE_P(dim));
1034                hval = Z_RES_HANDLE_P(dim);
1035                goto num_index;
1036            case IS_FALSE:
1037                hval = 0;
1038                goto num_index;
1039            case IS_TRUE:
1040                hval = 1;
1041                goto num_index;
1042            default:
1043                zend_error(E_WARNING, "Illegal offset type");
1044                retval = (type == BP_VAR_W || type == BP_VAR_RW) ?
1045                    &EG(error_zval) : &EG(uninitialized_zval);
1046        }
1047    }
1048    return retval;
1049}
1050
1051static zend_never_inline zend_long zend_check_string_offset(zval *container, zval *dim, int type TSRMLS_DC)
1052{
1053    zend_long offset;
1054
1055    if (dim == NULL) {
1056        zend_error_noreturn(E_ERROR, "[] operator not supported for strings");
1057    }
1058
1059    if (UNEXPECTED(Z_TYPE_P(dim) != IS_LONG)) {
1060        switch(Z_TYPE_P(dim)) {
1061            case IS_STRING:
1062                if (IS_LONG == is_numeric_string(Z_STRVAL_P(dim), Z_STRLEN_P(dim), NULL, NULL, -1)) {
1063                    break;
1064                }
1065                if (type != BP_VAR_UNSET) {
1066                    zend_error(E_WARNING, "Illegal string offset '%s'", Z_STRVAL_P(dim));
1067                }
1068                break;
1069            case IS_DOUBLE:
1070            case IS_NULL:
1071            case IS_FALSE:
1072            case IS_TRUE:
1073                zend_error(E_NOTICE, "String offset cast occurred");
1074                break;
1075            default:
1076                zend_error(E_WARNING, "Illegal offset type");
1077                break;
1078        }
1079
1080        offset = zval_get_long(dim);
1081    } else {
1082        offset = Z_LVAL_P(dim);
1083    }
1084
1085    return offset;
1086}
1087
1088static zend_always_inline zend_long zend_fetch_string_offset(zval *container, zval *dim, int type TSRMLS_DC)
1089{
1090    zend_long offset = zend_check_string_offset(container, dim, type TSRMLS_CC);
1091
1092    if (Z_REFCOUNTED_P(container)) {
1093        if (Z_REFCOUNT_P(container) > 1) {
1094            Z_DELREF_P(container);
1095            zval_copy_ctor_func(container);
1096        }
1097        Z_ADDREF_P(container);
1098    }
1099    return offset;
1100}
1101
1102static zend_always_inline void zend_fetch_dimension_address(zval *result, zval *container, zval *dim, int dim_type, int type TSRMLS_DC)
1103{
1104    zval *retval;
1105
1106    if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
1107        SEPARATE_ARRAY(container);
1108fetch_from_array:
1109        if (dim == NULL) {
1110            retval = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval));
1111            if (UNEXPECTED(retval == NULL)) {
1112                zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied");
1113                retval = &EG(error_zval);
1114            }
1115        } else {
1116            retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, dim_type, type TSRMLS_CC);
1117        }
1118        ZVAL_INDIRECT(result, retval);
1119    } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) {
1120        if (type != BP_VAR_UNSET && UNEXPECTED(Z_STRLEN_P(container) == 0)) {
1121            zval_ptr_dtor_nogc(container);
1122convert_to_array:
1123            ZVAL_NEW_ARR(container);
1124            zend_hash_init(Z_ARRVAL_P(container), 8, NULL, ZVAL_PTR_DTOR, 0);
1125            goto fetch_from_array;
1126        }
1127
1128        zend_check_string_offset(container, dim, type TSRMLS_CC);
1129
1130        ZVAL_INDIRECT(result, NULL); /* wrong string offset */
1131    } else if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
1132        if (!Z_OBJ_HT_P(container)->read_dimension) {
1133            zend_error_noreturn(E_ERROR, "Cannot use object as array");
1134        } else {
1135            retval = Z_OBJ_HT_P(container)->read_dimension(container, dim, type, result TSRMLS_CC);
1136
1137            if (UNEXPECTED(retval == &EG(uninitialized_zval))) {
1138                zend_class_entry *ce = Z_OBJCE_P(container);
1139
1140                ZVAL_NULL(result);
1141                zend_error(E_NOTICE, "Indirect modification of overloaded element of %s has no effect", ce->name->val);
1142            } else if (EXPECTED(retval && Z_TYPE_P(retval) != IS_UNDEF)) {
1143                if (!Z_ISREF_P(retval)) {
1144                    if (Z_REFCOUNTED_P(retval) &&
1145                        Z_REFCOUNT_P(retval) > 1) {
1146                        if (Z_TYPE_P(retval) != IS_OBJECT) {
1147                            Z_DELREF_P(retval);
1148                            ZVAL_DUP(result, retval);
1149                            retval = result;
1150                        } else {
1151                            ZVAL_COPY(result, retval);
1152                            retval = result;
1153                        }
1154                    }
1155                    if (Z_TYPE_P(retval) != IS_OBJECT) {
1156                        zend_class_entry *ce = Z_OBJCE_P(container);
1157                        zend_error(E_NOTICE, "Indirect modification of overloaded element of %s has no effect", ce->name->val);
1158                    }
1159                }
1160                if (result != retval) {
1161                    ZVAL_INDIRECT(result, retval);
1162                }
1163            } else {
1164                ZVAL_INDIRECT(result, &EG(error_zval));
1165            }
1166        }
1167    } else if (EXPECTED(Z_TYPE_P(container) == IS_NULL)) {
1168        if (UNEXPECTED(container == &EG(error_zval))) {
1169            ZVAL_INDIRECT(result, &EG(error_zval));
1170        } else if (type != BP_VAR_UNSET) {
1171            goto convert_to_array;
1172        } else {
1173            /* for read-mode only */
1174            ZVAL_NULL(result);
1175        }
1176    } else {
1177        if (type != BP_VAR_UNSET &&
1178            Z_TYPE_P(container) == IS_FALSE) {
1179            goto convert_to_array;
1180        }
1181        if (type == BP_VAR_UNSET) {
1182            zend_error(E_WARNING, "Cannot unset offset in a non-array variable");
1183            ZVAL_NULL(result);
1184        } else {
1185            zend_error(E_WARNING, "Cannot use a scalar value as an array");
1186            ZVAL_INDIRECT(result, &EG(error_zval));
1187        }
1188    }
1189}
1190
1191static zend_never_inline void zend_fetch_dimension_address_W(zval *result, zval *container_ptr, zval *dim, int dim_type TSRMLS_DC)
1192{
1193    zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_W TSRMLS_CC);
1194}
1195
1196static zend_never_inline void zend_fetch_dimension_address_RW(zval *result, zval *container_ptr, zval *dim, int dim_type TSRMLS_DC)
1197{
1198    zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_RW TSRMLS_CC);
1199}
1200
1201static zend_never_inline void zend_fetch_dimension_address_UNSET(zval *result, zval *container_ptr, zval *dim, int dim_type TSRMLS_DC)
1202{
1203    zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_UNSET TSRMLS_CC);
1204}
1205
1206static zend_always_inline void zend_fetch_dimension_address_read(zval *result, zval *container, zval *dim, int dim_type, int type TSRMLS_DC)
1207{
1208    zval *retval;
1209
1210    ZVAL_DEREF(container);
1211    if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
1212        retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, dim_type, type TSRMLS_CC);
1213        ZVAL_COPY(result, retval);
1214    } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) {
1215        zend_long offset;
1216
1217        if (UNEXPECTED(Z_TYPE_P(dim) != IS_LONG)) {
1218            switch(Z_TYPE_P(dim)) {
1219                /* case IS_LONG: */
1220                case IS_STRING:
1221                    if (IS_LONG == is_numeric_string(Z_STRVAL_P(dim), Z_STRLEN_P(dim), NULL, NULL, -1)) {
1222                        break;
1223                    }
1224                    if (type != BP_VAR_IS) {
1225                        zend_error(E_WARNING, "Illegal string offset '%s'", Z_STRVAL_P(dim));
1226                    }
1227                    break;
1228                case IS_DOUBLE:
1229                case IS_NULL:
1230                case IS_FALSE:
1231                case IS_TRUE:
1232                    if (type != BP_VAR_IS) {
1233                        zend_error(E_NOTICE, "String offset cast occurred");
1234                    }
1235                    break;
1236                default:
1237                    zend_error(E_WARNING, "Illegal offset type");
1238                    break;
1239            }
1240
1241            offset = zval_get_long(dim);
1242        } else {
1243            offset = Z_LVAL_P(dim);
1244        }
1245
1246        if (UNEXPECTED(offset < 0) || UNEXPECTED(Z_STRLEN_P(container) <= (size_t)offset)) {
1247            if (type != BP_VAR_IS) {
1248                zend_error(E_NOTICE, "Uninitialized string offset: %pd", offset);
1249            }
1250            ZVAL_EMPTY_STRING(result);
1251        } else {
1252            zend_uchar c = (zend_uchar)Z_STRVAL_P(container)[offset];
1253
1254            if (CG(one_char_string)[c]) {
1255                ZVAL_INTERNED_STR(result, CG(one_char_string)[c]);
1256            } else {
1257                ZVAL_NEW_STR(result, zend_string_init(Z_STRVAL_P(container) + offset, 1, 0));
1258            }
1259        }
1260    } else if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
1261        if (!Z_OBJ_HT_P(container)->read_dimension) {
1262            zend_error_noreturn(E_ERROR, "Cannot use object as array");
1263        } else {
1264            retval = Z_OBJ_HT_P(container)->read_dimension(container, dim, type, result TSRMLS_CC);
1265
1266            ZEND_ASSERT(result != NULL);
1267            if (retval) {
1268                if (result != retval) {
1269                    ZVAL_COPY(result, retval);
1270                }
1271            } else {
1272                ZVAL_NULL(result);
1273            }
1274        }
1275    } else {
1276        ZVAL_NULL(result);
1277    }
1278}
1279
1280static zend_never_inline void zend_fetch_dimension_address_read_R(zval *result, zval *container, zval *dim, int dim_type TSRMLS_DC)
1281{
1282    zend_fetch_dimension_address_read(result, container, dim, dim_type, BP_VAR_R TSRMLS_CC);
1283}
1284
1285static zend_never_inline void zend_fetch_dimension_address_read_IS(zval *result, zval *container, zval *dim, int dim_type TSRMLS_DC)
1286{
1287    zend_fetch_dimension_address_read(result, container, dim, dim_type, BP_VAR_IS TSRMLS_CC);
1288}
1289
1290ZEND_API void zend_fetch_dimension_by_zval(zval *result, zval *container, zval *dim TSRMLS_DC)
1291{
1292    zend_fetch_dimension_address_read_R(result, container, dim, IS_TMP_VAR TSRMLS_CC);
1293}
1294
1295static zend_always_inline void zend_fetch_property_address(zval *result, zval *container, uint32_t container_op_type, zval *prop_ptr, void **cache_slot, int type TSRMLS_DC)
1296{
1297    if (container_op_type != IS_UNUSED) {
1298        ZVAL_DEREF(container);
1299        if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
1300            if (UNEXPECTED(container == &EG(error_zval))) {
1301                ZVAL_INDIRECT(result, &EG(error_zval));
1302                return;
1303            }
1304
1305            /* this should modify object only if it's empty */
1306            if (type != BP_VAR_UNSET &&
1307                EXPECTED((Z_TYPE_P(container) == IS_NULL ||
1308                  Z_TYPE_P(container) == IS_FALSE ||
1309                  (Z_TYPE_P(container) == IS_STRING && Z_STRLEN_P(container)==0)))) {
1310                zval_ptr_dtor_nogc(container);
1311                object_init(container);
1312            } else {
1313                zend_error(E_WARNING, "Attempt to modify property of non-object");
1314                ZVAL_INDIRECT(result, &EG(error_zval));
1315                return;
1316            }
1317        }
1318    }
1319    if (EXPECTED(Z_OBJ_HT_P(container)->get_property_ptr_ptr)) {
1320        zval *ptr = Z_OBJ_HT_P(container)->get_property_ptr_ptr(container, prop_ptr, type, cache_slot TSRMLS_CC);
1321        if (NULL == ptr) {
1322            if (Z_OBJ_HT_P(container)->read_property &&
1323                (ptr = Z_OBJ_HT_P(container)->read_property(container, prop_ptr, type, cache_slot, result TSRMLS_CC)) != NULL) {
1324                if (ptr != result) {
1325                    ZVAL_INDIRECT(result, ptr);
1326                }
1327            } else {
1328                zend_error_noreturn(E_ERROR, "Cannot access undefined property for object with overloaded property access");
1329            }
1330        } else {
1331            ZVAL_INDIRECT(result, ptr);
1332        }
1333    } else if (EXPECTED(Z_OBJ_HT_P(container)->read_property)) {
1334        zval *ptr = Z_OBJ_HT_P(container)->read_property(container, prop_ptr, type, cache_slot, result TSRMLS_CC);
1335        if (ptr != result) {
1336            ZVAL_INDIRECT(result, ptr);
1337        }
1338    } else {
1339        zend_error(E_WARNING, "This object doesn't support property references");
1340        ZVAL_INDIRECT(result, &EG(error_zval));
1341    }
1342}
1343
1344static inline zend_brk_cont_element* zend_brk_cont(int nest_levels, int array_offset, const zend_op_array *op_array, const zend_execute_data *execute_data TSRMLS_DC)
1345{
1346    int original_nest_levels = nest_levels;
1347    zend_brk_cont_element *jmp_to;
1348
1349    do {
1350        if (array_offset==-1) {
1351            zend_error_noreturn(E_ERROR, "Cannot break/continue %d level%s", original_nest_levels, (original_nest_levels == 1) ? "" : "s");
1352        }
1353        jmp_to = &op_array->brk_cont_array[array_offset];
1354        if (nest_levels>1) {
1355            zend_op *brk_opline = &op_array->opcodes[jmp_to->brk];
1356
1357            if (brk_opline->opcode == ZEND_FREE) {
1358                if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
1359                    zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var));
1360                }
1361            }
1362        }
1363        array_offset = jmp_to->parent;
1364    } while (--nest_levels > 0);
1365    return jmp_to;
1366}
1367
1368#if ZEND_INTENSIVE_DEBUGGING
1369
1370#define CHECK_SYMBOL_TABLES()                                                   \
1371    zend_hash_apply(&EG(symbol_table), zend_check_symbol TSRMLS_CC);            \
1372    if (&EG(symbol_table)!=EX(symbol_table)) {                          \
1373        zend_hash_apply(EX(symbol_table), zend_check_symbol TSRMLS_CC); \
1374    }
1375
1376static int zend_check_symbol(zval *pz TSRMLS_DC)
1377{
1378    if (Z_TYPE_P(pz) == IS_INDIRECT) {
1379        pz = Z_INDIRECT_P(pz);
1380    }
1381    if (Z_TYPE_P(pz) > 10) {
1382        fprintf(stderr, "Warning!  %x has invalid type!\n", *pz);
1383/* See http://support.microsoft.com/kb/190351 */
1384#ifdef PHP_WIN32
1385        fflush(stderr);
1386#endif
1387    } else if (Z_TYPE_P(pz) == IS_ARRAY) {
1388        zend_hash_apply(Z_ARRVAL_P(pz), zend_check_symbol TSRMLS_CC);
1389    } else if (Z_TYPE_P(pz) == IS_OBJECT) {
1390        /* OBJ-TBI - doesn't support new object model! */
1391        zend_hash_apply(Z_OBJPROP_P(pz), zend_check_symbol TSRMLS_CC);
1392    }
1393
1394    return 0;
1395}
1396
1397
1398#else
1399#define CHECK_SYMBOL_TABLES()
1400#endif
1401
1402ZEND_API opcode_handler_t *zend_opcode_handlers;
1403
1404ZEND_API void execute_internal(zend_execute_data *execute_data, zval *return_value TSRMLS_DC)
1405{
1406    execute_data->func->internal_function.handler(execute_data, return_value TSRMLS_CC);
1407}
1408
1409ZEND_API void zend_clean_and_cache_symbol_table(zend_array *symbol_table TSRMLS_DC) /* {{{ */
1410{
1411    if (EG(symtable_cache_ptr) >= EG(symtable_cache_limit)) {
1412        zend_hash_destroy(&symbol_table->ht);
1413        efree_size(symbol_table, sizeof(zend_array));
1414    } else {
1415        /* clean before putting into the cache, since clean
1416           could call dtors, which could use cached hash */
1417        zend_hash_clean(&symbol_table->ht);
1418        *(++EG(symtable_cache_ptr)) = symbol_table;
1419    }
1420}
1421/* }}} */
1422
1423static zend_always_inline void i_free_compiled_variables(zend_execute_data *execute_data TSRMLS_DC) /* {{{ */
1424{
1425    if (EXPECTED(EX(func)->op_array.last_var > 0)) {
1426        zval *cv = EX_VAR_NUM(0);
1427        zval *end = cv + EX(func)->op_array.last_var;
1428        do {
1429            zval_ptr_dtor(cv);
1430            cv++;
1431        } while (cv != end);
1432    }
1433}
1434/* }}} */
1435
1436void zend_free_compiled_variables(zend_execute_data *execute_data TSRMLS_DC) /* {{{ */
1437{
1438    i_free_compiled_variables(execute_data TSRMLS_CC);
1439}
1440/* }}} */
1441
1442/*
1443 * Stack Frame Layout (the whole stack frame is allocated at once)
1444 * ==================
1445 *
1446 *                             +========================================+
1447 * EG(current_execute_data) -> | zend_execute_data                      |
1448 *                             +----------------------------------------+
1449 *     EX_CV_NUM(0) ---------> | VAR[0] = ARG[1]                        |
1450 *                             | ...                                    |
1451 *                             | VAR[op_array->num_args-1] = ARG[N]     |
1452 *                             | ...                                    |
1453 *                             | VAR[op_array->last_var-1]              |
1454 *                             | VAR[op_array->last_var] = TMP[0]       |
1455 *                             | ...                                    |
1456 *                             | VAR[op_array->last_var+op_array->T-1]  |
1457 *                             | ARG[N+1] (extra_args)                  |
1458 *                             | ...                                    |
1459 *                             +----------------------------------------+
1460 */
1461
1462static zend_always_inline void i_init_func_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value TSRMLS_DC) /* {{{ */
1463{
1464    uint32_t first_extra_arg, num_args;
1465    ZEND_ASSERT(EX(func) == (zend_function*)op_array);
1466    ZEND_ASSERT(EX(scope) == EG(scope));
1467
1468    EX(opline) = op_array->opcodes;
1469    EX(call) = NULL;
1470    EX(return_value) = return_value;
1471    EX(delayed_exception) = NULL;
1472    EX(silence_op_num) = -1;
1473
1474    /* Handle arguments */
1475    first_extra_arg = op_array->num_args;
1476    if (UNEXPECTED((op_array->fn_flags & ZEND_ACC_VARIADIC) != 0)) {
1477        first_extra_arg--;
1478    }
1479    num_args = EX(num_args);
1480    if (UNEXPECTED(num_args > first_extra_arg)) {
1481        zval *end, *src, *dst;
1482
1483        if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) {
1484            /* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */
1485            EX(opline) += first_extra_arg;
1486        }
1487
1488        /* move extra args into separate array after all CV and TMP vars */
1489        end = EX_VAR_NUM(first_extra_arg - 1);
1490        src = end + (num_args - first_extra_arg);
1491        dst = src + (op_array->last_var + op_array->T - first_extra_arg);
1492        if (EXPECTED(src != dst)) {
1493            do {
1494                ZVAL_COPY_VALUE(dst, src);
1495                ZVAL_UNDEF(src);
1496                src--;
1497                dst--;
1498            } while (src != end);
1499        }
1500    } else if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) {
1501        /* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */
1502        EX(opline) += num_args;
1503    }
1504
1505    /* Initialize CV variables (skip arguments) */
1506    if (EXPECTED((int)num_args < op_array->last_var)) {
1507        zval *var = EX_VAR_NUM(num_args);
1508        zval *end = EX_VAR_NUM(op_array->last_var);
1509
1510        do {
1511            ZVAL_UNDEF(var);
1512            var++;
1513        } while (var != end);
1514    }
1515
1516    if (op_array->this_var != -1 && Z_OBJ(EX(This))) {
1517        ZVAL_OBJ(EX_VAR(op_array->this_var), Z_OBJ(EX(This)));
1518        GC_REFCOUNT(Z_OBJ(EX(This)))++;
1519    }
1520
1521    if (!op_array->run_time_cache && op_array->last_cache_slot) {
1522        op_array->run_time_cache = zend_arena_calloc(&CG(arena), op_array->last_cache_slot, sizeof(void*));
1523    }
1524    EX(run_time_cache) = op_array->run_time_cache;
1525
1526    EG(current_execute_data) = execute_data;
1527}
1528/* }}} */
1529
1530static zend_always_inline void i_init_code_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value TSRMLS_DC) /* {{{ */
1531{
1532    ZEND_ASSERT(EX(func) == (zend_function*)op_array);
1533
1534    EX(opline) = op_array->opcodes;
1535    EX(call) = NULL;
1536    EX(return_value) = return_value;
1537    EX(scope) = EG(scope);
1538    EX(delayed_exception) = NULL;
1539    EX(silence_op_num) = -1;
1540
1541    zend_attach_symbol_table(execute_data);
1542
1543    if (op_array->this_var != -1 && Z_OBJ(EX(This))) {
1544        ZVAL_OBJ(EX_VAR(op_array->this_var), Z_OBJ(EX(This)));
1545        GC_REFCOUNT(Z_OBJ(EX(This)))++;
1546    }
1547
1548    if (!op_array->run_time_cache && op_array->last_cache_slot) {
1549        op_array->run_time_cache = ecalloc(op_array->last_cache_slot, sizeof(void*));
1550    }
1551    EX(run_time_cache) = op_array->run_time_cache;
1552
1553    EG(current_execute_data) = execute_data;
1554}
1555/* }}} */
1556
1557static zend_always_inline void i_init_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value TSRMLS_DC) /* {{{ */
1558{
1559    ZEND_ASSERT(EX(func) == (zend_function*)op_array);
1560
1561    EX(opline) = op_array->opcodes;
1562    EX(call) = NULL;
1563    EX(return_value) = return_value;
1564    EX(scope) = EG(scope);
1565    EX(delayed_exception) = NULL;
1566    EX(silence_op_num) = -1;
1567
1568    if (UNEXPECTED(EX(symbol_table) != NULL)) {
1569        zend_attach_symbol_table(execute_data);
1570    } else {
1571        uint32_t first_extra_arg, num_args;
1572
1573        /* Handle arguments */
1574        first_extra_arg = op_array->num_args;
1575        if (UNEXPECTED((op_array->fn_flags & ZEND_ACC_VARIADIC) != 0)) {
1576            first_extra_arg--;
1577        }
1578        num_args = EX(num_args);
1579        if (UNEXPECTED(num_args > first_extra_arg)) {
1580            zval *end, *src, *dst;
1581
1582            if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) {
1583                /* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */
1584                EX(opline) += first_extra_arg;
1585            }
1586
1587            /* move extra args into separate array after all CV and TMP vars */
1588            end = EX_VAR_NUM(first_extra_arg - 1);
1589            src = end + (num_args - first_extra_arg);
1590            dst = src + (op_array->last_var + op_array->T - first_extra_arg);
1591            if (EXPECTED(src != dst)) {
1592                do {
1593                    ZVAL_COPY_VALUE(dst, src);
1594                    ZVAL_UNDEF(src);
1595                    src--;
1596                    dst--;
1597                } while (src != end);
1598            }
1599        } else if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) {
1600            /* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */
1601            EX(opline) += num_args;
1602        }
1603
1604        /* Initialize CV variables (skip arguments) */
1605        if (EXPECTED((int)num_args < op_array->last_var)) {
1606            zval *var = EX_VAR_NUM(num_args);
1607            zval *end = EX_VAR_NUM(op_array->last_var);
1608
1609            do {
1610                ZVAL_UNDEF(var);
1611                var++;
1612            } while (var != end);
1613        }
1614    }
1615
1616    if (op_array->this_var != -1 && Z_OBJ(EX(This))) {
1617        ZVAL_OBJ(EX_VAR(op_array->this_var), Z_OBJ(EX(This)));
1618        GC_REFCOUNT(Z_OBJ(EX(This)))++;
1619    }
1620
1621    if (!op_array->run_time_cache && op_array->last_cache_slot) {
1622        if (op_array->function_name) {
1623            op_array->run_time_cache = zend_arena_calloc(&CG(arena), op_array->last_cache_slot, sizeof(void*));
1624        } else {
1625            op_array->run_time_cache = ecalloc(op_array->last_cache_slot, sizeof(void*));
1626        }
1627    }
1628    EX(run_time_cache) = op_array->run_time_cache;
1629
1630    EG(current_execute_data) = execute_data;
1631}
1632/* }}} */
1633
1634ZEND_API zend_execute_data *zend_create_generator_execute_data(zend_execute_data *call, zend_op_array *op_array, zval *return_value TSRMLS_DC) /* {{{ */
1635{
1636    /*
1637     * Normally the execute_data is allocated on the VM stack (because it does
1638     * not actually do any allocation and thus is faster). For generators
1639     * though this behavior would be suboptimal, because the (rather large)
1640     * structure would have to be copied back and forth every time execution is
1641     * suspended or resumed. That's why for generators the execution context
1642     * is allocated using a separate VM stack, thus allowing to save and
1643     * restore it simply by replacing a pointer.
1644     */
1645    zend_execute_data *execute_data;
1646    uint32_t num_args = call->num_args;
1647    size_t stack_size = (ZEND_CALL_FRAME_SLOT + MAX(op_array->last_var + op_array->T, num_args)) * sizeof(zval);
1648
1649    EG(vm_stack) = zend_vm_stack_new_page(
1650        EXPECTED(stack_size < ZEND_VM_STACK_FREE_PAGE_SIZE) ?
1651            ZEND_VM_STACK_PAGE_SIZE :
1652            ZEND_VM_STACK_PAGE_ALIGNED_SIZE(stack_size),
1653        NULL);
1654    EG(vm_stack_top) = EG(vm_stack)->top;
1655    EG(vm_stack_end) = EG(vm_stack)->end;
1656
1657    execute_data = zend_vm_stack_push_call_frame(
1658        VM_FRAME_TOP_FUNCTION,
1659        (zend_function*)op_array,
1660        num_args,
1661        call->called_scope,
1662        Z_OBJ(call->This),
1663        NULL TSRMLS_CC);
1664    EX(num_args) = num_args;
1665
1666    /* copy arguments */
1667    if (num_args > 0) {
1668        zval *arg_src = ZEND_CALL_ARG(call, 1);
1669        zval *arg_dst = ZEND_CALL_ARG(execute_data, 1);
1670        uint32_t i;
1671
1672        for (i = 0; i < num_args; i++) {
1673            ZVAL_COPY_VALUE(arg_dst + i, arg_src + i);
1674        }
1675    }
1676
1677    EX(symbol_table) = NULL;
1678    EX(scope) = EG(scope);
1679
1680    i_init_func_execute_data(execute_data, op_array, return_value TSRMLS_CC);
1681
1682    return execute_data;
1683}
1684/* }}} */
1685
1686ZEND_API void zend_init_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value TSRMLS_DC) /* {{{ */
1687{
1688    EX(prev_execute_data) = EG(current_execute_data);
1689    i_init_execute_data(execute_data, op_array, return_value TSRMLS_CC);
1690}
1691/* }}} */
1692
1693static zend_always_inline zend_bool zend_is_by_ref_func_arg_fetch(const zend_op *opline, zend_execute_data *call TSRMLS_DC) /* {{{ */
1694{
1695    uint32_t arg_num = opline->extended_value & ZEND_FETCH_ARG_MASK;
1696    return ARG_SHOULD_BE_SENT_BY_REF(call->func, arg_num);
1697}
1698/* }}} */
1699
1700static zend_execute_data *zend_vm_stack_copy_call_frame(zend_execute_data *call, uint32_t passed_args, uint32_t additional_args TSRMLS_DC) /* {{{ */
1701{
1702    zend_execute_data *new_call;
1703    int used_stack = (EG(vm_stack_top) - (zval*)call) + additional_args;
1704
1705    /* copy call frame into new stack segment */
1706    new_call = zend_vm_stack_extend(used_stack * sizeof(zval) TSRMLS_CC);
1707    *new_call = *call;
1708    if (passed_args) {
1709        zval *src = ZEND_CALL_ARG(call, 1);
1710        zval *dst = ZEND_CALL_ARG(new_call, 1);
1711        do {
1712            ZVAL_COPY_VALUE(dst, src);
1713            passed_args--;
1714            src++;
1715            dst++;
1716        } while (passed_args);
1717    }
1718
1719    /* delete old call_frame from previous stack segment */
1720    EG(vm_stack)->prev->top = (zval*)call;
1721
1722    /* delete previous stack segment if it becames empty */
1723    if (UNEXPECTED(EG(vm_stack)->prev->top == ZEND_VM_STACK_ELEMETS(EG(vm_stack)->prev))) {
1724        zend_vm_stack r = EG(vm_stack)->prev;
1725
1726        EG(vm_stack)->prev = r->prev;
1727        efree(r);
1728    }
1729
1730    return new_call;
1731}
1732/* }}} */
1733
1734static zend_always_inline void zend_vm_stack_extend_call_frame(zend_execute_data **call, uint32_t passed_args, uint32_t additional_args TSRMLS_DC) /* {{{ */
1735{
1736    if (EXPECTED(EG(vm_stack_end) - EG(vm_stack_top) > additional_args)) {
1737        EG(vm_stack_top) += additional_args;
1738    } else {
1739        *call = zend_vm_stack_copy_call_frame(*call, passed_args, additional_args TSRMLS_CC);
1740    }
1741}
1742/* }}} */
1743
1744#define ZEND_VM_NEXT_OPCODE() \
1745    CHECK_SYMBOL_TABLES() \
1746    ZEND_VM_INC_OPCODE(); \
1747    ZEND_VM_CONTINUE()
1748
1749#define ZEND_VM_SET_OPCODE(new_op) \
1750    CHECK_SYMBOL_TABLES() \
1751    OPLINE = new_op
1752
1753#define ZEND_VM_SET_RELATIVE_OPCODE(opline, offset) \
1754    CHECK_SYMBOL_TABLES() \
1755    OPLINE = ((zend_op*)(((char*)opline)+(offset)))
1756
1757#define ZEND_VM_JMP(new_op) \
1758    if (EXPECTED(!EG(exception))) { \
1759        ZEND_VM_SET_OPCODE(new_op); \
1760    } else { \
1761        LOAD_OPLINE(); \
1762    } \
1763    ZEND_VM_CONTINUE()
1764
1765#define ZEND_VM_INC_OPCODE() \
1766    OPLINE++
1767
1768#ifdef __GNUC__
1769# define ZEND_VM_GUARD(name) __asm__("#" #name)
1770#else
1771# define ZEND_VM_GUARD(name)
1772#endif
1773
1774#include "zend_vm_execute.h"
1775
1776ZEND_API int zend_set_user_opcode_handler(zend_uchar opcode, user_opcode_handler_t handler)
1777{
1778    if (opcode != ZEND_USER_OPCODE) {
1779        if (handler == NULL) {
1780            /* restore the original handler */
1781            zend_user_opcodes[opcode] = opcode;
1782        } else {
1783            zend_user_opcodes[opcode] = ZEND_USER_OPCODE;
1784        }
1785        zend_user_opcode_handlers[opcode] = handler;
1786        return SUCCESS;
1787    }
1788    return FAILURE;
1789}
1790
1791ZEND_API user_opcode_handler_t zend_get_user_opcode_handler(zend_uchar opcode)
1792{
1793    return zend_user_opcode_handlers[opcode];
1794}
1795
1796ZEND_API zval *zend_get_zval_ptr(int op_type, const znode_op *node, const zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC) {
1797    return get_zval_ptr(op_type, node, execute_data, should_free, type);
1798}
1799
1800/*
1801 * Local variables:
1802 * tab-width: 4
1803 * c-basic-offset: 4
1804 * indent-tabs-mode: t
1805 * End:
1806 */
1807