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