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