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