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