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, zend_ulong fetch_type, 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, (fetch_type | 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, zend_ulong fetch_type 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, fetch_type, &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, fetch_type, &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, zend_ulong fetch_type 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, fetch_type, &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, EX(opline)->extended_value 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, int is_ref 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        if (is_ref) {
1119            ZVAL_MAKE_REF(retval);
1120        }
1121        ZVAL_INDIRECT(result, retval);
1122    } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) {
1123        if (type != BP_VAR_UNSET && UNEXPECTED(Z_STRLEN_P(container) == 0)) {
1124            zval_ptr_dtor_nogc(container);
1125convert_to_array:
1126            ZVAL_NEW_ARR(container);
1127            zend_hash_init(Z_ARRVAL_P(container), 8, NULL, ZVAL_PTR_DTOR, 0);
1128            goto fetch_from_array;
1129        }
1130
1131        zend_check_string_offset(container, dim, type TSRMLS_CC);
1132
1133        ZVAL_INDIRECT(result, NULL); /* wrong string offset */
1134    } else if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
1135        if (!Z_OBJ_HT_P(container)->read_dimension) {
1136            zend_error_noreturn(E_ERROR, "Cannot use object as array");
1137        } else {
1138            retval = Z_OBJ_HT_P(container)->read_dimension(container, dim, type, result TSRMLS_CC);
1139
1140            if (UNEXPECTED(retval == &EG(uninitialized_zval))) {
1141                zend_class_entry *ce = Z_OBJCE_P(container);
1142
1143                ZVAL_NULL(result);
1144                zend_error(E_NOTICE, "Indirect modification of overloaded element of %s has no effect", ce->name->val);
1145            } else if (EXPECTED(retval && Z_TYPE_P(retval) != IS_UNDEF)) {
1146                if (!Z_ISREF_P(retval)) {
1147                    if (Z_REFCOUNTED_P(retval) &&
1148                        Z_REFCOUNT_P(retval) > 1) {
1149                        if (Z_TYPE_P(retval) != IS_OBJECT) {
1150                            Z_DELREF_P(retval);
1151                            ZVAL_DUP(result, retval);
1152                            retval = result;
1153                        } else {
1154                            ZVAL_COPY(result, retval);
1155                            retval = result;
1156                        }
1157                    }
1158                    if (Z_TYPE_P(retval) != IS_OBJECT) {
1159                        zend_class_entry *ce = Z_OBJCE_P(container);
1160                        zend_error(E_NOTICE, "Indirect modification of overloaded element of %s has no effect", ce->name->val);
1161                    }
1162                }
1163                if (result != retval) {
1164                    if (is_ref) {
1165                        ZVAL_MAKE_REF(retval);
1166                    }
1167                    ZVAL_INDIRECT(result, retval);
1168                }
1169            } else {
1170                ZVAL_INDIRECT(result, &EG(error_zval));
1171            }
1172        }
1173    } else if (EXPECTED(Z_TYPE_P(container) == IS_NULL)) {
1174        if (UNEXPECTED(container == &EG(error_zval))) {
1175            ZVAL_INDIRECT(result, &EG(error_zval));
1176        } else if (type != BP_VAR_UNSET) {
1177            goto convert_to_array;
1178        } else {
1179            /* for read-mode only */
1180            ZVAL_NULL(result);
1181        }
1182    } else {
1183        if (type != BP_VAR_UNSET &&
1184            Z_TYPE_P(container) == IS_FALSE) {
1185            goto convert_to_array;
1186        }
1187        if (type == BP_VAR_UNSET) {
1188            zend_error(E_WARNING, "Cannot unset offset in a non-array variable");
1189            ZVAL_NULL(result);
1190        } else {
1191            zend_error(E_WARNING, "Cannot use a scalar value as an array");
1192            ZVAL_INDIRECT(result, &EG(error_zval));
1193        }
1194    }
1195}
1196
1197static zend_never_inline void zend_fetch_dimension_address_W(zval *result, zval *container_ptr, zval *dim, int dim_type TSRMLS_DC)
1198{
1199    zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_W, 0 TSRMLS_CC);
1200}
1201
1202static zend_never_inline void zend_fetch_dimension_address_W_ref(zval *result, zval *container_ptr, zval *dim, int dim_type TSRMLS_DC)
1203{
1204    zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_W, 1 TSRMLS_CC);
1205}
1206
1207static zend_never_inline void zend_fetch_dimension_address_RW(zval *result, zval *container_ptr, zval *dim, int dim_type TSRMLS_DC)
1208{
1209    zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_RW, 0 TSRMLS_CC);
1210}
1211
1212static zend_never_inline void zend_fetch_dimension_address_UNSET(zval *result, zval *container_ptr, zval *dim, int dim_type TSRMLS_DC)
1213{
1214    zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_UNSET, 0 TSRMLS_CC);
1215}
1216
1217static zend_always_inline void zend_fetch_dimension_address_read(zval *result, zval *container, zval *dim, int dim_type, int type TSRMLS_DC)
1218{
1219    zval *retval;
1220
1221    ZVAL_DEREF(container);
1222    if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
1223        retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, dim_type, type TSRMLS_CC);
1224        ZVAL_COPY(result, retval);
1225    } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) {
1226        zend_long offset;
1227
1228        if (UNEXPECTED(Z_TYPE_P(dim) != IS_LONG)) {
1229            switch(Z_TYPE_P(dim)) {
1230                /* case IS_LONG: */
1231                case IS_STRING:
1232                    if (IS_LONG == is_numeric_string(Z_STRVAL_P(dim), Z_STRLEN_P(dim), NULL, NULL, -1)) {
1233                        break;
1234                    }
1235                    if (type != BP_VAR_IS) {
1236                        zend_error(E_WARNING, "Illegal string offset '%s'", Z_STRVAL_P(dim));
1237                    }
1238                    break;
1239                case IS_DOUBLE:
1240                case IS_NULL:
1241                case IS_FALSE:
1242                case IS_TRUE:
1243                    if (type != BP_VAR_IS) {
1244                        zend_error(E_NOTICE, "String offset cast occurred");
1245                    }
1246                    break;
1247                default:
1248                    zend_error(E_WARNING, "Illegal offset type");
1249                    break;
1250            }
1251
1252            offset = zval_get_long(dim);
1253        } else {
1254            offset = Z_LVAL_P(dim);
1255        }
1256
1257        if (UNEXPECTED(offset < 0) || UNEXPECTED(Z_STRLEN_P(container) <= (size_t)offset)) {
1258            if (type != BP_VAR_IS) {
1259                zend_error(E_NOTICE, "Uninitialized string offset: %pd", offset);
1260            }
1261            ZVAL_EMPTY_STRING(result);
1262        } else {
1263            zend_uchar c = (zend_uchar)Z_STRVAL_P(container)[offset];
1264
1265            if (CG(one_char_string)[c]) {
1266                ZVAL_INTERNED_STR(result, CG(one_char_string)[c]);
1267            } else {
1268                ZVAL_NEW_STR(result, zend_string_init(Z_STRVAL_P(container) + offset, 1, 0));
1269            }
1270        }
1271    } else if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
1272        if (!Z_OBJ_HT_P(container)->read_dimension) {
1273            zend_error_noreturn(E_ERROR, "Cannot use object as array");
1274        } else {
1275            retval = Z_OBJ_HT_P(container)->read_dimension(container, dim, type, result TSRMLS_CC);
1276
1277            ZEND_ASSERT(result != NULL);
1278            if (retval) {
1279                if (result != retval) {
1280                    ZVAL_COPY(result, retval);
1281                }
1282            } else {
1283                ZVAL_NULL(result);
1284            }
1285        }
1286    } else {
1287        ZVAL_NULL(result);
1288    }
1289}
1290
1291static zend_never_inline void zend_fetch_dimension_address_read_R(zval *result, zval *container, zval *dim, int dim_type TSRMLS_DC)
1292{
1293    zend_fetch_dimension_address_read(result, container, dim, dim_type, BP_VAR_R TSRMLS_CC);
1294}
1295
1296static zend_never_inline void zend_fetch_dimension_address_read_IS(zval *result, zval *container, zval *dim, int dim_type TSRMLS_DC)
1297{
1298    zend_fetch_dimension_address_read(result, container, dim, dim_type, BP_VAR_IS TSRMLS_CC);
1299}
1300
1301ZEND_API void zend_fetch_dimension_by_zval(zval *result, zval *container, zval *dim TSRMLS_DC)
1302{
1303    zend_fetch_dimension_address_read_R(result, container, dim, IS_TMP_VAR TSRMLS_CC);
1304}
1305
1306static 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, int is_ref TSRMLS_DC)
1307{
1308    if (container_op_type != IS_UNUSED) {
1309        ZVAL_DEREF(container);
1310        if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
1311            if (UNEXPECTED(container == &EG(error_zval))) {
1312                ZVAL_INDIRECT(result, &EG(error_zval));
1313                return;
1314            }
1315
1316            /* this should modify object only if it's empty */
1317            if (type != BP_VAR_UNSET &&
1318                EXPECTED((Z_TYPE_P(container) == IS_NULL ||
1319                  Z_TYPE_P(container) == IS_FALSE ||
1320                  (Z_TYPE_P(container) == IS_STRING && Z_STRLEN_P(container)==0)))) {
1321                zval_ptr_dtor_nogc(container);
1322                object_init(container);
1323            } else {
1324                zend_error(E_WARNING, "Attempt to modify property of non-object");
1325                ZVAL_INDIRECT(result, &EG(error_zval));
1326                return;
1327            }
1328        }
1329    }
1330    if (EXPECTED(Z_OBJ_HT_P(container)->get_property_ptr_ptr)) {
1331        zval *ptr = Z_OBJ_HT_P(container)->get_property_ptr_ptr(container, prop_ptr, type, cache_slot TSRMLS_CC);
1332        if (NULL == ptr) {
1333            if (Z_OBJ_HT_P(container)->read_property &&
1334                (ptr = Z_OBJ_HT_P(container)->read_property(container, prop_ptr, type, cache_slot, result TSRMLS_CC)) != NULL) {
1335                if (ptr != result) {
1336                    if (is_ref && ptr != &EG(uninitialized_zval)) {
1337                        ZVAL_MAKE_REF(ptr);
1338                    }
1339                    ZVAL_INDIRECT(result, ptr);
1340                }
1341            } else {
1342                zend_error_noreturn(E_ERROR, "Cannot access undefined property for object with overloaded property access");
1343            }
1344        } else {
1345            if (is_ref) {
1346                ZVAL_MAKE_REF(ptr);
1347            }
1348            ZVAL_INDIRECT(result, ptr);
1349        }
1350    } else if (EXPECTED(Z_OBJ_HT_P(container)->read_property)) {
1351        zval *ptr = Z_OBJ_HT_P(container)->read_property(container, prop_ptr, type, cache_slot, result TSRMLS_CC);
1352        if (ptr != result) {
1353            if (is_ref && ptr != &EG(uninitialized_zval)) {
1354                ZVAL_MAKE_REF(ptr);
1355            }
1356            ZVAL_INDIRECT(result, ptr);
1357        }
1358    } else {
1359        zend_error(E_WARNING, "This object doesn't support property references");
1360        ZVAL_INDIRECT(result, &EG(error_zval));
1361    }
1362}
1363
1364static 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)
1365{
1366    int original_nest_levels = nest_levels;
1367    zend_brk_cont_element *jmp_to;
1368
1369    do {
1370        if (array_offset==-1) {
1371            zend_error_noreturn(E_ERROR, "Cannot break/continue %d level%s", original_nest_levels, (original_nest_levels == 1) ? "" : "s");
1372        }
1373        jmp_to = &op_array->brk_cont_array[array_offset];
1374        if (nest_levels>1) {
1375            zend_op *brk_opline = &op_array->opcodes[jmp_to->brk];
1376
1377            if (brk_opline->opcode == ZEND_FREE) {
1378                if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
1379                    zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var));
1380                }
1381            }
1382        }
1383        array_offset = jmp_to->parent;
1384    } while (--nest_levels > 0);
1385    return jmp_to;
1386}
1387
1388#if ZEND_INTENSIVE_DEBUGGING
1389
1390#define CHECK_SYMBOL_TABLES()                                                   \
1391    zend_hash_apply(&EG(symbol_table), zend_check_symbol TSRMLS_CC);            \
1392    if (&EG(symbol_table)!=EX(symbol_table)) {                          \
1393        zend_hash_apply(EX(symbol_table), zend_check_symbol TSRMLS_CC); \
1394    }
1395
1396static int zend_check_symbol(zval *pz TSRMLS_DC)
1397{
1398    if (Z_TYPE_P(pz) == IS_INDIRECT) {
1399        pz = Z_INDIRECT_P(pz);
1400    }
1401    if (Z_TYPE_P(pz) > 10) {
1402        fprintf(stderr, "Warning!  %x has invalid type!\n", *pz);
1403/* See http://support.microsoft.com/kb/190351 */
1404#ifdef PHP_WIN32
1405        fflush(stderr);
1406#endif
1407    } else if (Z_TYPE_P(pz) == IS_ARRAY) {
1408        zend_hash_apply(Z_ARRVAL_P(pz), zend_check_symbol TSRMLS_CC);
1409    } else if (Z_TYPE_P(pz) == IS_OBJECT) {
1410        /* OBJ-TBI - doesn't support new object model! */
1411        zend_hash_apply(Z_OBJPROP_P(pz), zend_check_symbol TSRMLS_CC);
1412    }
1413
1414    return 0;
1415}
1416
1417
1418#else
1419#define CHECK_SYMBOL_TABLES()
1420#endif
1421
1422ZEND_API opcode_handler_t *zend_opcode_handlers;
1423
1424ZEND_API void execute_internal(zend_execute_data *execute_data, zval *return_value TSRMLS_DC)
1425{
1426    execute_data->func->internal_function.handler(execute_data, return_value TSRMLS_CC);
1427}
1428
1429ZEND_API void zend_clean_and_cache_symbol_table(zend_array *symbol_table TSRMLS_DC) /* {{{ */
1430{
1431    if (EG(symtable_cache_ptr) >= EG(symtable_cache_limit)) {
1432        zend_hash_destroy(&symbol_table->ht);
1433        efree_size(symbol_table, sizeof(zend_array));
1434    } else {
1435        /* clean before putting into the cache, since clean
1436           could call dtors, which could use cached hash */
1437        zend_hash_clean(&symbol_table->ht);
1438        *(++EG(symtable_cache_ptr)) = symbol_table;
1439    }
1440}
1441/* }}} */
1442
1443static zend_always_inline void i_free_compiled_variables(zend_execute_data *execute_data TSRMLS_DC) /* {{{ */
1444{
1445    if (EXPECTED(EX(func)->op_array.last_var > 0)) {
1446        zval *cv = EX_VAR_NUM(0);
1447        zval *end = cv + EX(func)->op_array.last_var;
1448        do {
1449            zval_ptr_dtor(cv);
1450            cv++;
1451        } while (cv != end);
1452    }
1453}
1454/* }}} */
1455
1456void zend_free_compiled_variables(zend_execute_data *execute_data TSRMLS_DC) /* {{{ */
1457{
1458    i_free_compiled_variables(execute_data TSRMLS_CC);
1459}
1460/* }}} */
1461
1462/*
1463 * Stack Frame Layout (the whole stack frame is allocated at once)
1464 * ==================
1465 *
1466 *                             +========================================+
1467 * EG(current_execute_data) -> | zend_execute_data                      |
1468 *                             +----------------------------------------+
1469 *     EX_CV_NUM(0) ---------> | VAR[0] = ARG[1]                        |
1470 *                             | ...                                    |
1471 *                             | VAR[op_array->num_args-1] = ARG[N]     |
1472 *                             | ...                                    |
1473 *                             | VAR[op_array->last_var-1]              |
1474 *                             | VAR[op_array->last_var] = TMP[0]       |
1475 *                             | ...                                    |
1476 *                             | VAR[op_array->last_var+op_array->T-1]  |
1477 *                             | ARG[N+1] (extra_args)                  |
1478 *                             | ...                                    |
1479 *                             +----------------------------------------+
1480 */
1481
1482static zend_always_inline void i_init_func_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value TSRMLS_DC) /* {{{ */
1483{
1484    uint32_t first_extra_arg, num_args;
1485    ZEND_ASSERT(EX(func) == (zend_function*)op_array);
1486    ZEND_ASSERT(EX(scope) == EG(scope));
1487
1488    EX(opline) = op_array->opcodes;
1489    EX(call) = NULL;
1490    EX(return_value) = return_value;
1491    EX(delayed_exception) = NULL;
1492    EX(silence_op_num) = -1;
1493
1494    /* Handle arguments */
1495    first_extra_arg = op_array->num_args;
1496    if (UNEXPECTED((op_array->fn_flags & ZEND_ACC_VARIADIC) != 0)) {
1497        first_extra_arg--;
1498    }
1499    num_args = EX(num_args);
1500    if (UNEXPECTED(num_args > first_extra_arg)) {
1501        zval *end, *src, *dst;
1502
1503        if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) {
1504            /* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */
1505            EX(opline) += first_extra_arg;
1506        }
1507
1508        /* move extra args into separate array after all CV and TMP vars */
1509        end = EX_VAR_NUM(first_extra_arg - 1);
1510        src = end + (num_args - first_extra_arg);
1511        dst = src + (op_array->last_var + op_array->T - first_extra_arg);
1512        if (EXPECTED(src != dst)) {
1513            do {
1514                ZVAL_COPY_VALUE(dst, src);
1515                ZVAL_UNDEF(src);
1516                src--;
1517                dst--;
1518            } while (src != end);
1519        }
1520    } else if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) {
1521        /* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */
1522        EX(opline) += num_args;
1523    }
1524
1525    /* Initialize CV variables (skip arguments) */
1526    if (EXPECTED((int)num_args < op_array->last_var)) {
1527        zval *var = EX_VAR_NUM(num_args);
1528        zval *end = EX_VAR_NUM(op_array->last_var);
1529
1530        do {
1531            ZVAL_UNDEF(var);
1532            var++;
1533        } while (var != end);
1534    }
1535
1536    if (op_array->this_var != -1 && Z_OBJ(EX(This))) {
1537        ZVAL_OBJ(EX_VAR(op_array->this_var), Z_OBJ(EX(This)));
1538        GC_REFCOUNT(Z_OBJ(EX(This)))++;
1539    }
1540
1541    if (!op_array->run_time_cache && op_array->last_cache_slot) {
1542        op_array->run_time_cache = zend_arena_calloc(&CG(arena), op_array->last_cache_slot, sizeof(void*));
1543    }
1544    EX(run_time_cache) = op_array->run_time_cache;
1545
1546    EG(current_execute_data) = execute_data;
1547}
1548/* }}} */
1549
1550static zend_always_inline void i_init_code_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value TSRMLS_DC) /* {{{ */
1551{
1552    ZEND_ASSERT(EX(func) == (zend_function*)op_array);
1553
1554    EX(opline) = op_array->opcodes;
1555    EX(call) = NULL;
1556    EX(return_value) = return_value;
1557    EX(scope) = EG(scope);
1558    EX(delayed_exception) = NULL;
1559    EX(silence_op_num) = -1;
1560
1561    zend_attach_symbol_table(execute_data);
1562
1563    if (op_array->this_var != -1 && Z_OBJ(EX(This))) {
1564        ZVAL_OBJ(EX_VAR(op_array->this_var), Z_OBJ(EX(This)));
1565        GC_REFCOUNT(Z_OBJ(EX(This)))++;
1566    }
1567
1568    if (!op_array->run_time_cache && op_array->last_cache_slot) {
1569        op_array->run_time_cache = ecalloc(op_array->last_cache_slot, sizeof(void*));
1570    }
1571    EX(run_time_cache) = op_array->run_time_cache;
1572
1573    EG(current_execute_data) = execute_data;
1574}
1575/* }}} */
1576
1577static zend_always_inline void i_init_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value TSRMLS_DC) /* {{{ */
1578{
1579    ZEND_ASSERT(EX(func) == (zend_function*)op_array);
1580
1581    EX(opline) = op_array->opcodes;
1582    EX(call) = NULL;
1583    EX(return_value) = return_value;
1584    EX(scope) = EG(scope);
1585    EX(delayed_exception) = NULL;
1586    EX(silence_op_num) = -1;
1587
1588    if (UNEXPECTED(EX(symbol_table) != NULL)) {
1589        zend_attach_symbol_table(execute_data);
1590    } else {
1591        uint32_t first_extra_arg, num_args;
1592
1593        /* Handle arguments */
1594        first_extra_arg = op_array->num_args;
1595        if (UNEXPECTED((op_array->fn_flags & ZEND_ACC_VARIADIC) != 0)) {
1596            first_extra_arg--;
1597        }
1598        num_args = EX(num_args);
1599        if (UNEXPECTED(num_args > first_extra_arg)) {
1600            zval *end, *src, *dst;
1601
1602            if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) {
1603                /* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */
1604                EX(opline) += first_extra_arg;
1605            }
1606
1607            /* move extra args into separate array after all CV and TMP vars */
1608            end = EX_VAR_NUM(first_extra_arg - 1);
1609            src = end + (num_args - first_extra_arg);
1610            dst = src + (op_array->last_var + op_array->T - first_extra_arg);
1611            if (EXPECTED(src != dst)) {
1612                do {
1613                    ZVAL_COPY_VALUE(dst, src);
1614                    ZVAL_UNDEF(src);
1615                    src--;
1616                    dst--;
1617                } while (src != end);
1618            }
1619        } else if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) {
1620            /* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */
1621            EX(opline) += num_args;
1622        }
1623
1624        /* Initialize CV variables (skip arguments) */
1625        if (EXPECTED((int)num_args < op_array->last_var)) {
1626            zval *var = EX_VAR_NUM(num_args);
1627            zval *end = EX_VAR_NUM(op_array->last_var);
1628
1629            do {
1630                ZVAL_UNDEF(var);
1631                var++;
1632            } while (var != end);
1633        }
1634    }
1635
1636    if (op_array->this_var != -1 && Z_OBJ(EX(This))) {
1637        ZVAL_OBJ(EX_VAR(op_array->this_var), Z_OBJ(EX(This)));
1638        GC_REFCOUNT(Z_OBJ(EX(This)))++;
1639    }
1640
1641    if (!op_array->run_time_cache && op_array->last_cache_slot) {
1642        if (op_array->function_name) {
1643            op_array->run_time_cache = zend_arena_calloc(&CG(arena), op_array->last_cache_slot, sizeof(void*));
1644        } else {
1645            op_array->run_time_cache = ecalloc(op_array->last_cache_slot, sizeof(void*));
1646        }
1647    }
1648    EX(run_time_cache) = op_array->run_time_cache;
1649
1650    EG(current_execute_data) = execute_data;
1651}
1652/* }}} */
1653
1654ZEND_API zend_execute_data *zend_create_generator_execute_data(zend_execute_data *call, zend_op_array *op_array, zval *return_value TSRMLS_DC) /* {{{ */
1655{
1656    /*
1657     * Normally the execute_data is allocated on the VM stack (because it does
1658     * not actually do any allocation and thus is faster). For generators
1659     * though this behavior would be suboptimal, because the (rather large)
1660     * structure would have to be copied back and forth every time execution is
1661     * suspended or resumed. That's why for generators the execution context
1662     * is allocated using a separate VM stack, thus allowing to save and
1663     * restore it simply by replacing a pointer.
1664     */
1665    zend_execute_data *execute_data;
1666    uint32_t num_args = call->num_args;
1667    size_t stack_size = (ZEND_CALL_FRAME_SLOT + MAX(op_array->last_var + op_array->T, num_args)) * sizeof(zval);
1668
1669    EG(vm_stack) = zend_vm_stack_new_page(
1670        EXPECTED(stack_size < ZEND_VM_STACK_FREE_PAGE_SIZE) ?
1671            ZEND_VM_STACK_PAGE_SIZE :
1672            ZEND_VM_STACK_PAGE_ALIGNED_SIZE(stack_size),
1673        NULL);
1674    EG(vm_stack_top) = EG(vm_stack)->top;
1675    EG(vm_stack_end) = EG(vm_stack)->end;
1676
1677    execute_data = zend_vm_stack_push_call_frame(
1678        VM_FRAME_TOP_FUNCTION,
1679        (zend_function*)op_array,
1680        num_args,
1681        call->called_scope,
1682        Z_OBJ(call->This),
1683        NULL TSRMLS_CC);
1684    EX(num_args) = num_args;
1685
1686    /* copy arguments */
1687    if (num_args > 0) {
1688        zval *arg_src = ZEND_CALL_ARG(call, 1);
1689        zval *arg_dst = ZEND_CALL_ARG(execute_data, 1);
1690        uint32_t i;
1691
1692        for (i = 0; i < num_args; i++) {
1693            ZVAL_COPY_VALUE(arg_dst + i, arg_src + i);
1694        }
1695    }
1696
1697    EX(symbol_table) = NULL;
1698    EX(scope) = EG(scope);
1699
1700    i_init_func_execute_data(execute_data, op_array, return_value TSRMLS_CC);
1701
1702    return execute_data;
1703}
1704/* }}} */
1705
1706ZEND_API void zend_init_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value TSRMLS_DC) /* {{{ */
1707{
1708    EX(prev_execute_data) = EG(current_execute_data);
1709    i_init_execute_data(execute_data, op_array, return_value TSRMLS_CC);
1710}
1711/* }}} */
1712
1713static zend_always_inline zend_bool zend_is_by_ref_func_arg_fetch(const zend_op *opline, zend_execute_data *call TSRMLS_DC) /* {{{ */
1714{
1715    uint32_t arg_num = opline->extended_value & ZEND_FETCH_ARG_MASK;
1716    return ARG_SHOULD_BE_SENT_BY_REF(call->func, arg_num);
1717}
1718/* }}} */
1719
1720static zend_execute_data *zend_vm_stack_copy_call_frame(zend_execute_data *call, uint32_t passed_args, uint32_t additional_args TSRMLS_DC) /* {{{ */
1721{
1722    zend_execute_data *new_call;
1723    int used_stack = (EG(vm_stack_top) - (zval*)call) + additional_args;
1724
1725    /* copy call frame into new stack segment */
1726    new_call = zend_vm_stack_extend(used_stack * sizeof(zval) TSRMLS_CC);
1727    *new_call = *call;
1728    if (passed_args) {
1729        zval *src = ZEND_CALL_ARG(call, 1);
1730        zval *dst = ZEND_CALL_ARG(new_call, 1);
1731        do {
1732            ZVAL_COPY_VALUE(dst, src);
1733            passed_args--;
1734            src++;
1735            dst++;
1736        } while (passed_args);
1737    }
1738
1739    /* delete old call_frame from previous stack segment */
1740    EG(vm_stack)->prev->top = (zval*)call;
1741
1742    /* delete previous stack segment if it becames empty */
1743    if (UNEXPECTED(EG(vm_stack)->prev->top == ZEND_VM_STACK_ELEMETS(EG(vm_stack)->prev))) {
1744        zend_vm_stack r = EG(vm_stack)->prev;
1745
1746        EG(vm_stack)->prev = r->prev;
1747        efree(r);
1748    }
1749
1750    return new_call;
1751}
1752/* }}} */
1753
1754static zend_always_inline void zend_vm_stack_extend_call_frame(zend_execute_data **call, uint32_t passed_args, uint32_t additional_args TSRMLS_DC) /* {{{ */
1755{
1756    if (EXPECTED(EG(vm_stack_end) - EG(vm_stack_top) > additional_args)) {
1757        EG(vm_stack_top) += additional_args;
1758    } else {
1759        *call = zend_vm_stack_copy_call_frame(*call, passed_args, additional_args TSRMLS_CC);
1760    }
1761}
1762/* }}} */
1763
1764#define ZEND_VM_NEXT_OPCODE() \
1765    CHECK_SYMBOL_TABLES() \
1766    ZEND_VM_INC_OPCODE(); \
1767    ZEND_VM_CONTINUE()
1768
1769#define ZEND_VM_SET_OPCODE(new_op) \
1770    CHECK_SYMBOL_TABLES() \
1771    OPLINE = new_op
1772
1773#define ZEND_VM_SET_RELATIVE_OPCODE(opline, offset) \
1774    CHECK_SYMBOL_TABLES() \
1775    OPLINE = ((zend_op*)(((char*)opline)+(offset)))
1776
1777#define ZEND_VM_JMP(new_op) \
1778    if (EXPECTED(!EG(exception))) { \
1779        ZEND_VM_SET_OPCODE(new_op); \
1780    } else { \
1781        LOAD_OPLINE(); \
1782    } \
1783    ZEND_VM_CONTINUE()
1784
1785#define ZEND_VM_INC_OPCODE() \
1786    OPLINE++
1787
1788#ifdef __GNUC__
1789# define ZEND_VM_GUARD(name) __asm__("#" #name)
1790#else
1791# define ZEND_VM_GUARD(name)
1792#endif
1793
1794#include "zend_vm_execute.h"
1795
1796ZEND_API int zend_set_user_opcode_handler(zend_uchar opcode, user_opcode_handler_t handler)
1797{
1798    if (opcode != ZEND_USER_OPCODE) {
1799        if (handler == NULL) {
1800            /* restore the original handler */
1801            zend_user_opcodes[opcode] = opcode;
1802        } else {
1803            zend_user_opcodes[opcode] = ZEND_USER_OPCODE;
1804        }
1805        zend_user_opcode_handlers[opcode] = handler;
1806        return SUCCESS;
1807    }
1808    return FAILURE;
1809}
1810
1811ZEND_API user_opcode_handler_t zend_get_user_opcode_handler(zend_uchar opcode)
1812{
1813    return zend_user_opcode_handlers[opcode];
1814}
1815
1816ZEND_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) {
1817    return get_zval_ptr(op_type, node, execute_data, should_free, type);
1818}
1819
1820/*
1821 * Local variables:
1822 * tab-width: 4
1823 * c-basic-offset: 4
1824 * indent-tabs-mode: t
1825 * End:
1826 */
1827