1/*
2   +----------------------------------------------------------------------+
3   | Zend Engine                                                          |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 1998-2014 Zend Technologies Ltd. (http://www.zend.com) |
6   +----------------------------------------------------------------------+
7   | This source file is subject to version 2.00 of the Zend license,     |
8   | that is bundled with this package in the file LICENSE, and is        |
9   | available through the world-wide-web at the following url:           |
10   | http://www.zend.com/license/2_00.txt.                                |
11   | If you did not receive a copy of the Zend license and are unable to  |
12   | obtain it through the world-wide-web, please send a note to          |
13   | license@zend.com so we can mail you a copy immediately.              |
14   +----------------------------------------------------------------------+
15   | Authors: Andi Gutmans <andi@zend.com>                                |
16   |          Zeev Suraski <zeev@zend.com>                                |
17   +----------------------------------------------------------------------+
18*/
19
20/* $Id$ */
21
22#define ZEND_INTENSIVE_DEBUGGING 0
23
24#include <stdio.h>
25#include <signal.h>
26
27#include "zend.h"
28#include "zend_compile.h"
29#include "zend_execute.h"
30#include "zend_API.h"
31#include "zend_ptr_stack.h"
32#include "zend_constants.h"
33#include "zend_extensions.h"
34#include "zend_ini.h"
35#include "zend_exceptions.h"
36#include "zend_interfaces.h"
37#include "zend_closures.h"
38#include "zend_generators.h"
39#include "zend_vm.h"
40#include "zend_dtrace.h"
41#include "zend_inheritance.h"
42
43/* Virtual current working directory support */
44#include "zend_virtual_cwd.h"
45
46#define _CONST_CODE  0
47#define _TMP_CODE    1
48#define _VAR_CODE    2
49#define _UNUSED_CODE 3
50#define _CV_CODE     4
51
52typedef int (*incdec_t)(zval *);
53
54#define get_zval_ptr(op_type, node, ex, should_free, type) _get_zval_ptr(op_type, node, ex, should_free, type TSRMLS_CC)
55#define get_zval_ptr_deref(op_type, node, ex, should_free, type) _get_zval_ptr_deref(op_type, node, ex, should_free, type TSRMLS_CC)
56#define get_zval_ptr_ptr(op_type, node, ex, should_free, type) _get_zval_ptr_ptr(op_type, node, ex, should_free, type TSRMLS_CC)
57#define get_zval_ptr_ptr_undef(op_type, node, ex, should_free, type) _get_zval_ptr_ptr(op_type, node, ex, should_free, type TSRMLS_CC)
58#define get_obj_zval_ptr(op_type, node, ex, should_free, type) _get_obj_zval_ptr(op_type, node, ex, should_free, type TSRMLS_CC)
59#define get_obj_zval_ptr_ptr(op_type, node, ex, should_free, type) _get_obj_zval_ptr_ptr(op_type, node, ex, should_free, type TSRMLS_CC)
60
61/* Prototypes */
62static void zend_extension_statement_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC);
63static void zend_extension_fcall_begin_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC);
64static void zend_extension_fcall_end_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC);
65
66#define RETURN_VALUE_USED(opline) (!((opline)->result_type & EXT_TYPE_UNUSED))
67
68static ZEND_FUNCTION(pass)
69{
70}
71
72static const zend_internal_function zend_pass_function = {
73    ZEND_INTERNAL_FUNCTION, /* type              */
74    0,                      /* fn_flags          */
75    NULL,                   /* name              */
76    NULL,                   /* scope             */
77    NULL,                   /* prototype         */
78    0,                      /* num_args          */
79    0,                      /* required_num_args */
80    NULL,                   /* arg_info          */
81    ZEND_FN(pass),          /* handler           */
82    NULL                    /* module            */
83};
84
85#undef zval_ptr_dtor
86#define zval_ptr_dtor(zv) i_zval_ptr_dtor(zv ZEND_FILE_LINE_CC TSRMLS_CC)
87
88#define PZVAL_LOCK(z) if (Z_REFCOUNTED_P(z)) Z_ADDREF_P((z))
89#define SELECTIVE_PZVAL_LOCK(pzv, opline)   if (RETURN_VALUE_USED(opline)) { PZVAL_LOCK(pzv); }
90
91#define READY_TO_DESTROY(zv) \
92    (zv && Z_REFCOUNTED_P(zv) && Z_REFCOUNT_P(zv) == 1)
93
94#define EXTRACT_ZVAL_PTR(zv) do {                       \
95        zval *__zv = (zv);                              \
96        if (Z_TYPE_P(__zv) == IS_INDIRECT) {            \
97            ZVAL_COPY(__zv, Z_INDIRECT_P(__zv));        \
98        }                                               \
99    } while (0)
100
101#define FREE_OP(should_free) \
102    if (should_free.var) { \
103        if ((zend_uintptr_t)should_free.var & 1L) { \
104            zval_dtor((zval*)((zend_uintptr_t)should_free.var & ~1L)); \
105        } else { \
106            zval_ptr_dtor_nogc(should_free.var); \
107        } \
108    }
109
110#define FREE_OP_IF_VAR(should_free) \
111    if (should_free.var != NULL && (((zend_uintptr_t)should_free.var & 1L) == 0)) { \
112        zval_ptr_dtor_nogc(should_free.var); \
113    }
114
115#define FREE_OP_VAR_PTR(should_free) \
116    if (should_free.var) { \
117        zval_ptr_dtor_nogc(should_free.var); \
118    }
119
120#define TMP_FREE(z) (zval*)(((zend_uintptr_t)(z)) | 1L)
121
122#define IS_TMP_FREE(should_free) ((zend_uintptr_t)should_free.var & 1L)
123
124/* End of zend_execute_locks.h */
125
126#define CV_DEF_OF(i) (EX(func)->op_array.vars[i])
127
128#define CTOR_CALL_BIT    0x1
129#define CTOR_USED_BIT    0x2
130
131#define IS_CTOR_CALL(ce) (((zend_uintptr_t)(ce)) & CTOR_CALL_BIT)
132#define IS_CTOR_USED(ce) (((zend_uintptr_t)(ce)) & CTOR_USED_BIT)
133
134#define ENCODE_CTOR(ce, used) \
135    ((zend_class_entry*)(((zend_uintptr_t)(ce)) | CTOR_CALL_BIT | ((used) ? CTOR_USED_BIT : 0)))
136#define DECODE_CTOR(ce) \
137    ((zend_class_entry*)(((zend_uintptr_t)(ce)) & ~(CTOR_CALL_BIT|CTOR_USED_BIT)))
138
139#undef EX
140#define EX(element) execute_data->element
141
142ZEND_API zval* zend_get_compiled_variable_value(const zend_execute_data *execute_data, uint32_t var)
143{
144    return EX_VAR(var);
145}
146
147static zend_always_inline zval *_get_zval_ptr_tmp(uint32_t var, const zend_execute_data *execute_data, zend_free_op *should_free TSRMLS_DC)
148{
149    zval *ret = EX_VAR(var);
150    should_free->var = ret;
151
152    ZEND_ASSERT(Z_TYPE_P(ret) != IS_REFERENCE);
153
154    return ret;
155}
156
157static zend_always_inline zval *_get_zval_ptr_var(uint32_t var, const zend_execute_data *execute_data, zend_free_op *should_free TSRMLS_DC)
158{
159    zval *ret = EX_VAR(var);
160
161    should_free->var = ret;
162    return ret;
163}
164
165static zend_always_inline zval *_get_zval_ptr_var_deref(uint32_t var, const zend_execute_data *execute_data, zend_free_op *should_free TSRMLS_DC)
166{
167    zval *ret = EX_VAR(var);
168
169    should_free->var = ret;
170    ZVAL_DEREF(ret);
171    return ret;
172}
173
174static zend_never_inline zval *_get_zval_cv_lookup(zval *ptr, uint32_t var, int type, const zend_execute_data *execute_data TSRMLS_DC)
175{
176    zend_string *cv;
177
178    switch (type) {
179        case BP_VAR_R:
180        case BP_VAR_UNSET:
181            cv = CV_DEF_OF(EX_VAR_TO_NUM(var));
182            zend_error(E_NOTICE, "Undefined variable: %s", cv->val);
183            /* break missing intentionally */
184        case BP_VAR_IS:
185            ptr = &EG(uninitialized_zval);
186            break;
187        case BP_VAR_RW:
188            cv = CV_DEF_OF(EX_VAR_TO_NUM(var));
189            zend_error(E_NOTICE, "Undefined variable: %s", cv->val);
190            /* break missing intentionally */
191        case BP_VAR_W:
192            ZVAL_NULL(ptr);
193            break;
194    }
195    return ptr;
196}
197
198static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_R(zval *ptr, uint32_t var, const zend_execute_data *execute_data TSRMLS_DC)
199{
200    zend_string *cv = CV_DEF_OF(EX_VAR_TO_NUM(var));
201
202    zend_error(E_NOTICE, "Undefined variable: %s", cv->val);
203    return &EG(uninitialized_zval);
204}
205
206static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_UNSET(zval *ptr, uint32_t var, const zend_execute_data *execute_data TSRMLS_DC)
207{
208    zend_string *cv = CV_DEF_OF(EX_VAR_TO_NUM(var));
209
210    zend_error(E_NOTICE, "Undefined variable: %s", cv->val);
211    return &EG(uninitialized_zval);
212}
213
214static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_RW(zval *ptr, uint32_t var, const zend_execute_data *execute_data TSRMLS_DC)
215{
216    zend_string *cv = CV_DEF_OF(EX_VAR_TO_NUM(var));
217
218    ZVAL_NULL(ptr);
219    zend_error(E_NOTICE, "Undefined variable: %s", cv->val);
220    return ptr;
221}
222
223static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_W(zval *ptr, uint32_t var, const zend_execute_data *execute_data TSRMLS_DC)
224{
225    ZVAL_NULL(ptr);
226    return ptr;
227}
228
229static zend_always_inline zval *_get_zval_ptr_cv(const zend_execute_data *execute_data, uint32_t var, int type TSRMLS_DC)
230{
231    zval *ret = EX_VAR(var);
232
233    if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
234        return _get_zval_cv_lookup(ret, var, type, execute_data TSRMLS_CC);
235    }
236    return ret;
237}
238
239static zend_always_inline zval *_get_zval_ptr_cv_deref(const zend_execute_data *execute_data, uint32_t var, int type TSRMLS_DC)
240{
241    zval *ret = EX_VAR(var);
242
243    if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
244        return _get_zval_cv_lookup(ret, var, type, execute_data TSRMLS_CC);
245    }
246    ZVAL_DEREF(ret);
247    return ret;
248}
249
250static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_R(const zend_execute_data *execute_data, uint32_t var TSRMLS_DC)
251{
252    zval *ret = EX_VAR(var);
253
254    if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
255        return _get_zval_cv_lookup_BP_VAR_R(ret, var, execute_data TSRMLS_CC);
256    }
257    return ret;
258}
259
260static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_R(const zend_execute_data *execute_data, uint32_t var TSRMLS_DC)
261{
262    zval *ret = EX_VAR(var);
263
264    if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
265        return _get_zval_cv_lookup_BP_VAR_R(ret, var, execute_data TSRMLS_CC);
266    }
267    ZVAL_DEREF(ret);
268    return ret;
269}
270
271static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_UNSET(const zend_execute_data *execute_data, uint32_t var TSRMLS_DC)
272{
273    zval *ret = EX_VAR(var);
274
275    if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
276        return _get_zval_cv_lookup_BP_VAR_UNSET(ret, var, execute_data TSRMLS_CC);
277    }
278    return ret;
279}
280
281static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_UNSET(const zend_execute_data *execute_data, uint32_t var TSRMLS_DC)
282{
283    zval *ret = EX_VAR(var);
284
285    if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
286        return _get_zval_cv_lookup_BP_VAR_UNSET(ret, var, execute_data TSRMLS_CC);
287    }
288    ZVAL_DEREF(ret);
289    return ret;
290}
291
292static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_IS(const zend_execute_data *execute_data, uint32_t var TSRMLS_DC)
293{
294    zval *ret = EX_VAR(var);
295
296    return ret;
297}
298
299static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_IS(const zend_execute_data *execute_data, uint32_t var TSRMLS_DC)
300{
301    zval *ret = EX_VAR(var);
302
303    ZVAL_DEREF(ret);
304    return ret;
305}
306
307static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_RW(const zend_execute_data *execute_data, uint32_t var TSRMLS_DC)
308{
309    zval *ret = EX_VAR(var);
310
311    if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
312        return _get_zval_cv_lookup_BP_VAR_RW(ret, var, execute_data TSRMLS_CC);
313    }
314    return ret;
315}
316
317static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_RW(const zend_execute_data *execute_data, uint32_t var TSRMLS_DC)
318{
319    zval *ret = EX_VAR(var);
320
321    if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
322        return _get_zval_cv_lookup_BP_VAR_RW(ret, var, execute_data TSRMLS_CC);
323    }
324    ZVAL_DEREF(ret);
325    return ret;
326}
327
328static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_W(const zend_execute_data *execute_data, uint32_t var TSRMLS_DC)
329{
330    zval *ret = EX_VAR(var);
331
332    if (Z_TYPE_P(ret) == IS_UNDEF) {
333        return _get_zval_cv_lookup_BP_VAR_W(ret, var, execute_data TSRMLS_CC);
334    }
335    return ret;
336}
337
338static zend_always_inline zval *_get_zval_ptr_cv_undef_BP_VAR_W(const zend_execute_data *execute_data, uint32_t var TSRMLS_DC)
339{
340    return EX_VAR(var);
341}
342
343static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_W(const zend_execute_data *execute_data, uint32_t var TSRMLS_DC)
344{
345    zval *ret = EX_VAR(var);
346
347    if (Z_TYPE_P(ret) == IS_UNDEF) {
348        return _get_zval_cv_lookup_BP_VAR_W(ret, var, execute_data TSRMLS_CC);
349    }
350    ZVAL_DEREF(ret);
351    return ret;
352}
353
354static inline zval *_get_zval_ptr(int op_type, const znode_op *node, const zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC)
355{
356    zval *ret;
357
358    switch (op_type) {
359        case IS_CONST:
360            should_free->var = NULL;
361            return node->zv;
362            break;
363        case IS_TMP_VAR:
364            ret = EX_VAR(node->var);
365            should_free->var = TMP_FREE(ret);
366            return ret;
367            break;
368        case IS_VAR:
369            return _get_zval_ptr_var(node->var, execute_data, should_free TSRMLS_CC);
370            break;
371        case IS_UNUSED:
372            should_free->var = NULL;
373            return NULL;
374            break;
375        case IS_CV:
376        default:
377            should_free->var = NULL;
378            return _get_zval_ptr_cv(execute_data, node->var, type TSRMLS_CC);
379            break;
380    }
381    return NULL;
382}
383
384static inline zval *_get_zval_ptr_deref(int op_type, const znode_op *node, const zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC)
385{
386    zval *ret;
387
388    switch (op_type) {
389        case IS_CONST:
390            should_free->var = NULL;
391            return node->zv;
392            break;
393        case IS_TMP_VAR:
394            ret = EX_VAR(node->var);
395            should_free->var = TMP_FREE(ret);
396            return ret;
397            break;
398        case IS_VAR:
399            return _get_zval_ptr_var_deref(node->var, execute_data, should_free TSRMLS_CC);
400            break;
401        case IS_UNUSED:
402            should_free->var = NULL;
403            return NULL;
404            break;
405        case IS_CV:
406        default:
407            should_free->var = NULL;
408            return _get_zval_ptr_cv_deref(execute_data, node->var, type TSRMLS_CC);
409            break;
410    }
411    return NULL;
412}
413
414static zend_always_inline zval *_get_zval_ptr_ptr_var(uint32_t var, const zend_execute_data *execute_data, zend_free_op *should_free TSRMLS_DC)
415{
416    zval *ret = EX_VAR(var);
417
418    if (EXPECTED(Z_TYPE_P(ret) == IS_INDIRECT)) {
419        should_free->var = NULL;
420        return Z_INDIRECT_P(ret);
421    } else if (!Z_REFCOUNTED_P(ret) || Z_REFCOUNT_P(ret) == 1) {
422        should_free->var = ret;
423        return ret;
424    } else {
425        Z_DELREF_P(ret);
426        should_free->var = NULL;
427        return ret;
428    }
429}
430
431static inline zval *_get_zval_ptr_ptr(int op_type, const znode_op *node, const zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC)
432{
433    if (op_type == IS_CV) {
434        should_free->var = NULL;
435        return _get_zval_ptr_cv(execute_data, node->var, type TSRMLS_CC);
436    } else /* if (op_type == IS_VAR) */ {
437        ZEND_ASSERT(op_type == IS_VAR);
438        return _get_zval_ptr_ptr_var(node->var, execute_data, should_free TSRMLS_CC);
439    }
440}
441
442static zend_always_inline zval *_get_obj_zval_ptr_unused(TSRMLS_D)
443{
444    if (EXPECTED(Z_OBJ(EG(This)) != NULL)) {
445        return &EG(This);
446    } else {
447        zend_error_noreturn(E_ERROR, "Using $this when not in object context");
448        return NULL;
449    }
450}
451
452static inline zval *_get_obj_zval_ptr(int op_type, znode_op *op, const zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC)
453{
454    if (op_type == IS_UNUSED) {
455        if (EXPECTED(Z_OBJ(EG(This)) != NULL)) {
456            should_free->var = NULL;
457            return &EG(This);
458        } else {
459            zend_error_noreturn(E_ERROR, "Using $this when not in object context");
460        }
461    }
462    return get_zval_ptr(op_type, op, execute_data, should_free, type);
463}
464
465static inline zval *_get_obj_zval_ptr_ptr(int op_type, const znode_op *node, const zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC)
466{
467    if (op_type == IS_UNUSED) {
468        if (EXPECTED(Z_OBJ(EG(This)) != NULL)) {
469            should_free->var = NULL;
470            return &EG(This);
471        } else {
472            zend_error_noreturn(E_ERROR, "Using $this when not in object context");
473        }
474    }
475    return get_zval_ptr_ptr(op_type, node, execute_data, should_free, type);
476}
477
478static inline void zend_assign_to_variable_reference(zval *variable_ptr, zval *value_ptr TSRMLS_DC)
479{
480    if (EXPECTED(variable_ptr != value_ptr)) {
481        ZVAL_MAKE_REF(value_ptr);
482        Z_ADDREF_P(value_ptr);
483        zval_ptr_dtor(variable_ptr);
484        ZVAL_REF(variable_ptr, Z_REF_P(value_ptr));
485    } else {
486        ZVAL_MAKE_REF(variable_ptr);
487    }
488}
489
490/* this should modify object only if it's empty */
491static inline zval* make_real_object(zval *object_ptr TSRMLS_DC)
492{
493    zval *object = object_ptr;
494
495    ZVAL_DEREF(object);
496    if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
497        if (Z_TYPE_P(object) == IS_NULL
498            || Z_TYPE_P(object) == IS_FALSE
499            || (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0)) {
500            zval_ptr_dtor_nogc(object);
501            object_init(object);
502            zend_error(E_WARNING, "Creating default object from empty value");
503        }
504    }
505    return object;
506}
507
508ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, zend_ulong fetch_type, char **class_name, zend_class_entry **pce TSRMLS_DC)
509{
510    zend_string *key;
511    ALLOCA_FLAG(use_heap);
512
513    STR_ALLOCA_INIT(key, cur_arg_info->class_name, cur_arg_info->class_name_len, use_heap);
514    *pce = zend_fetch_class(key, (fetch_type | ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD) TSRMLS_CC);
515    STR_ALLOCA_FREE(key, use_heap);
516
517    *class_name = (*pce) ? (*pce)->name->val : (char*)cur_arg_info->class_name;
518    if (*pce && (*pce)->ce_flags & ZEND_ACC_INTERFACE) {
519        return "implement interface ";
520    } else {
521        return "be an instance of ";
522    }
523}
524
525ZEND_API void zend_verify_arg_error(int error_type, const zend_function *zf, uint32_t arg_num, const char *need_msg, const char *need_kind, const char *given_msg, const char *given_kind, zval *arg TSRMLS_DC)
526{
527    zend_execute_data *ptr = EG(current_execute_data)->prev_execute_data;
528    const char *fname = zf->common.function_name->val;
529    const char *fsep;
530    const char *fclass;
531    zval old_arg;
532
533    if (zf->common.scope) {
534        fsep =  "::";
535        fclass = zf->common.scope->name->val;
536    } else {
537        fsep =  "";
538        fclass = "";
539    }
540
541    if (arg && zf->common.type == ZEND_USER_FUNCTION) {
542        ZVAL_COPY_VALUE(&old_arg, arg);
543        ZVAL_UNDEF(arg);
544    }
545
546    if (zf->common.type == ZEND_USER_FUNCTION && ptr && ptr->func && ZEND_USER_CODE(ptr->func->common.type)) {
547        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);
548    } else {
549        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);
550    }
551
552    if (arg && zf->common.type == ZEND_USER_FUNCTION) {
553        ZVAL_COPY_VALUE(arg, &old_arg);
554    }
555}
556
557static void zend_verify_arg_type(zend_function *zf, uint32_t arg_num, zval *arg, zend_ulong fetch_type TSRMLS_DC)
558{
559    zend_arg_info *cur_arg_info;
560    char *need_msg;
561    zend_class_entry *ce;
562
563    if (UNEXPECTED(!zf->common.arg_info)) {
564        return;
565    }
566
567    if (EXPECTED(arg_num <= zf->common.num_args)) {
568        cur_arg_info = &zf->common.arg_info[arg_num-1];
569    } else if (zf->common.fn_flags & ZEND_ACC_VARIADIC) {
570        cur_arg_info = &zf->common.arg_info[zf->common.num_args-1];
571    } else {
572        return;
573    }
574
575    if (cur_arg_info->class_name) {
576        char *class_name;
577
578        ZVAL_DEREF(arg);
579        if (Z_TYPE_P(arg) == IS_OBJECT) {
580            need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC);
581            if (!ce || !instanceof_function(Z_OBJCE_P(arg), ce TSRMLS_CC)) {
582                zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, "instance of ", Z_OBJCE_P(arg)->name->val, arg TSRMLS_CC);
583            }
584        } else if (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null) {
585            need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC);
586            zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, zend_zval_type_name(arg), "", arg TSRMLS_CC);
587        }
588    } else if (cur_arg_info->type_hint) {
589        if (cur_arg_info->type_hint == IS_ARRAY) {
590            ZVAL_DEREF(arg);
591            if (Z_TYPE_P(arg) != IS_ARRAY && (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null)) {
592                zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be of the type array", "", zend_zval_type_name(arg), "", arg TSRMLS_CC);
593            }
594        } else if (cur_arg_info->type_hint == IS_CALLABLE) {
595            if (!zend_is_callable(arg, IS_CALLABLE_CHECK_SILENT, NULL TSRMLS_CC) && (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null)) {
596                zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be callable", "", zend_zval_type_name(arg), "", arg TSRMLS_CC);
597            }
598#if ZEND_DEBUG
599        } else {
600            zend_error(E_ERROR, "Unknown typehint");
601#endif
602        }
603    }
604}
605
606static inline int zend_verify_missing_arg_type(zend_function *zf, uint32_t arg_num, zend_ulong fetch_type TSRMLS_DC)
607{
608    zend_arg_info *cur_arg_info;
609    char *need_msg;
610    zend_class_entry *ce;
611
612    if (UNEXPECTED(!zf->common.arg_info)) {
613        return 1;
614    }
615
616    if (EXPECTED(arg_num <= zf->common.num_args)) {
617        cur_arg_info = &zf->common.arg_info[arg_num-1];
618    } else if (zf->common.fn_flags & ZEND_ACC_VARIADIC) {
619        cur_arg_info = &zf->common.arg_info[zf->common.num_args-1];
620    } else {
621        return 1;
622    }
623
624    if (cur_arg_info->class_name) {
625        char *class_name;
626
627        need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC);
628        zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, "none", "", NULL TSRMLS_CC);
629        return 0;
630    } else if (cur_arg_info->type_hint) {
631        if (cur_arg_info->type_hint == IS_ARRAY) {
632            zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be of the type array", "", "none", "", NULL TSRMLS_CC);
633        } else if (cur_arg_info->type_hint == IS_CALLABLE) {
634            zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be callable", "", "none", "", NULL TSRMLS_CC);
635#if ZEND_DEBUG
636        } else {
637            zend_error(E_ERROR, "Unknown typehint");
638#endif
639        }
640        return 0;
641    }
642    return 1;
643}
644
645static void zend_verify_missing_arg(zend_execute_data *execute_data, uint32_t arg_num TSRMLS_DC)
646{
647    if (EXPECTED(!(EX(func)->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS)) ||
648        zend_verify_missing_arg_type(EX(func), arg_num, EX(opline)->extended_value TSRMLS_CC)) {
649        const char *class_name = EX(func)->common.scope ? EX(func)->common.scope->name->val : "";
650        const char *space = EX(func)->common.scope ? "::" : "";
651        const char *func_name = EX(func)->common.function_name ? EX(func)->common.function_name->val : "main";
652        zend_execute_data *ptr = EX(prev_execute_data);
653
654        if (ptr && ptr->func && ZEND_USER_CODE(ptr->func->common.type)) {
655            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);
656        } else {
657            zend_error(E_WARNING, "Missing argument %u for %s%s%s()", arg_num, class_name, space, func_name);
658        }
659    }
660}
661
662static inline void zend_assign_to_object(zval *retval, zval *object_ptr, zval *property_name, int value_type, const znode_op *value_op, const zend_execute_data *execute_data, int opcode, void **cache_slot TSRMLS_DC)
663{
664    zend_free_op free_value;
665    zval *value = get_zval_ptr(value_type, value_op, execute_data, &free_value, BP_VAR_R);
666    zval tmp;
667    zval *object = object_ptr;
668
669    ZVAL_DEREF(object);
670    if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
671        if (UNEXPECTED(object == &EG(error_zval))) {
672            if (retval) {
673                ZVAL_NULL(retval);
674            }
675            FREE_OP(free_value);
676            return;
677        }
678        if (EXPECTED(Z_TYPE_P(object) == IS_NULL ||
679            Z_TYPE_P(object) == IS_FALSE ||
680            (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) {
681            zend_object *obj;
682
683            zval_ptr_dtor(object);
684            object_init(object);
685            Z_ADDREF_P(object);
686            obj = Z_OBJ_P(object);
687            zend_error(E_WARNING, "Creating default object from empty value");
688            if (GC_REFCOUNT(obj) == 1) {
689                /* the enclosing container was deleted, obj is unreferenced */
690                if (retval) {
691                    ZVAL_NULL(retval);
692                }
693                FREE_OP(free_value);
694                OBJ_RELEASE(obj);
695                return;
696            }
697            Z_DELREF_P(object);
698        } else {
699            zend_error(E_WARNING, "Attempt to assign property of non-object");
700            if (retval) {
701                ZVAL_NULL(retval);
702            }
703            FREE_OP(free_value);
704            return;
705        }
706    }
707
708    /* separate our value if necessary */
709    if (value_type == IS_TMP_VAR) {
710        ZVAL_COPY_VALUE(&tmp, value);
711        value = &tmp;
712    } else if (value_type == IS_CONST) {
713        if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
714            ZVAL_COPY_VALUE(&tmp, value);
715            zval_copy_ctor_func(&tmp);
716            value = &tmp;
717        }
718    } else if (Z_REFCOUNTED_P(value)) {
719        Z_ADDREF_P(value);
720    }
721
722    if (opcode == ZEND_ASSIGN_OBJ) {
723        if (!Z_OBJ_HT_P(object)->write_property) {
724            zend_error(E_WARNING, "Attempt to assign property of non-object");
725            if (retval) {
726                ZVAL_NULL(retval);
727            }
728            if (value_type == IS_CONST) {
729                zval_ptr_dtor(value);
730            }
731            FREE_OP(free_value);
732            return;
733        }
734        Z_OBJ_HT_P(object)->write_property(object, property_name, value, cache_slot TSRMLS_CC);
735    } else {
736        /* Note:  property_name in this case is really the array index! */
737        if (!Z_OBJ_HT_P(object)->write_dimension) {
738            zend_error_noreturn(E_ERROR, "Cannot use object as array");
739        }
740        Z_OBJ_HT_P(object)->write_dimension(object, property_name, value TSRMLS_CC);
741    }
742
743    if (retval && !EG(exception)) {
744        ZVAL_COPY(retval, value);
745    }
746    zval_ptr_dtor(value);
747    FREE_OP_IF_VAR(free_value);
748}
749
750static void zend_assign_to_string_offset(zval *str, zend_long offset, zval *value, int value_type, zval *result TSRMLS_DC)
751{
752    zend_string *old_str;
753
754    if (offset < 0) {
755        zend_error(E_WARNING, "Illegal string offset:  " ZEND_LONG_FMT, offset);
756        zend_string_release(Z_STR_P(str));
757        if (result) {
758            ZVAL_NULL(result);
759        }
760        return;
761    }
762
763    old_str = Z_STR_P(str);
764    if ((size_t)offset >= Z_STRLEN_P(str)) {
765        zend_long old_len = Z_STRLEN_P(str);
766        Z_STR_P(str) = zend_string_realloc(Z_STR_P(str), offset + 1, 0);
767        Z_TYPE_INFO_P(str) = IS_STRING_EX;
768        memset(Z_STRVAL_P(str) + old_len, ' ', offset - old_len);
769        Z_STRVAL_P(str)[offset+1] = 0;
770    } else if (!Z_REFCOUNTED_P(str)) {
771        Z_STR_P(str) = zend_string_init(Z_STRVAL_P(str), Z_STRLEN_P(str), 0);
772        Z_TYPE_INFO_P(str) = IS_STRING_EX;
773    }
774
775    if (Z_TYPE_P(value) != IS_STRING) {
776        zend_string *tmp = zval_get_string(value);
777
778        Z_STRVAL_P(str)[offset] = tmp->val[0];
779        zend_string_release(tmp);
780    } else {
781        Z_STRVAL_P(str)[offset] = Z_STRVAL_P(value)[0];
782        if (value_type == IS_TMP_VAR) {
783            /* we can safely free final_value here
784             * because separation is done only
785             * in case value_type == IS_VAR */
786            zval_dtor(value);
787        }
788    }
789    /*
790     * the value of an assignment to a string offset is undefined
791    T(result->u.var).var = &T->str_offset.str;
792    */
793
794    zend_string_release(old_str);
795    if (result) {
796        zend_uchar c = (zend_uchar)Z_STRVAL_P(str)[offset];
797
798        if (CG(one_char_string)[c]) {
799            ZVAL_INTERNED_STR(result, CG(one_char_string)[c]);
800        } else {
801            ZVAL_NEW_STR(result, zend_string_init(Z_STRVAL_P(str) + offset, 1, 0));
802        }
803    }
804}
805
806static zend_always_inline zval* zend_assign_to_variable(zval *variable_ptr, zval *value, zend_uchar value_type TSRMLS_DC)
807{
808    do {
809        if (UNEXPECTED(Z_REFCOUNTED_P(variable_ptr))) {
810            zend_refcounted *garbage;
811
812            if (Z_ISREF_P(variable_ptr)) {
813                variable_ptr = Z_REFVAL_P(variable_ptr);
814                if (EXPECTED(!Z_REFCOUNTED_P(variable_ptr))) {
815                    break;
816                }
817            }
818            if (Z_TYPE_P(variable_ptr) == IS_OBJECT &&
819                UNEXPECTED(Z_OBJ_HANDLER_P(variable_ptr, set) != NULL)) {
820                Z_OBJ_HANDLER_P(variable_ptr, set)(variable_ptr, value TSRMLS_CC);
821                return variable_ptr;
822            }
823            if ((value_type & (IS_VAR|IS_CV)) && variable_ptr == value) {
824                return variable_ptr;
825            }
826            garbage = Z_COUNTED_P(variable_ptr);
827            if (GC_REFCOUNT(garbage) == 1) {
828                ZVAL_COPY_VALUE(variable_ptr, value);
829                if (value_type == IS_CONST) {
830                    /* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */
831                    if (UNEXPECTED(Z_OPT_COPYABLE_P(variable_ptr))) {
832                        zval_copy_ctor_func(variable_ptr);
833                    }
834                } else if (value_type != IS_TMP_VAR) {
835                    if (UNEXPECTED(Z_OPT_REFCOUNTED_P(variable_ptr))) {
836                        Z_ADDREF_P(variable_ptr);
837                    }
838                }
839                _zval_dtor_func(garbage ZEND_FILE_LINE_CC);
840                return variable_ptr;
841            } else { /* we need to split */
842                GC_REFCOUNT(garbage)--;
843                /* optimized version of GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr) */
844                if ((Z_COLLECTABLE_P(variable_ptr)) &&
845                    UNEXPECTED(!GC_INFO(garbage))) {
846                    gc_possible_root(garbage TSRMLS_CC);
847                }
848            }
849        }
850    } while (0);
851
852    ZVAL_COPY_VALUE(variable_ptr, value);
853    if (value_type == IS_CONST) {
854        /* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */
855        if (UNEXPECTED(Z_OPT_COPYABLE_P(variable_ptr))) {
856            zval_copy_ctor_func(variable_ptr);
857        }
858    } else if (value_type != IS_TMP_VAR) {
859        if (UNEXPECTED(Z_OPT_REFCOUNTED_P(variable_ptr))) {
860            Z_ADDREF_P(variable_ptr);
861        }
862    }
863    return variable_ptr;
864}
865
866/* Utility Functions for Extensions */
867static void zend_extension_statement_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC)
868{
869    if (extension->statement_handler) {
870        extension->statement_handler(op_array);
871    }
872}
873
874
875static void zend_extension_fcall_begin_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC)
876{
877    if (extension->fcall_begin_handler) {
878        extension->fcall_begin_handler(op_array);
879    }
880}
881
882
883static void zend_extension_fcall_end_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC)
884{
885    if (extension->fcall_end_handler) {
886        extension->fcall_end_handler(op_array);
887    }
888}
889
890
891static zend_always_inline HashTable *zend_get_target_symbol_table(zend_execute_data *execute_data, int fetch_type TSRMLS_DC)
892{
893    HashTable *ht;
894
895    if (EXPECTED(fetch_type == ZEND_FETCH_GLOBAL_LOCK) ||
896        EXPECTED(fetch_type == ZEND_FETCH_GLOBAL)) {
897        ht = &EG(symbol_table).ht;
898    } else if (EXPECTED(fetch_type == ZEND_FETCH_STATIC)) {
899        ZEND_ASSERT(EX(func)->op_array.static_variables != NULL);
900        ht = EX(func)->op_array.static_variables;
901    } else {
902        ZEND_ASSERT(fetch_type == ZEND_FETCH_LOCAL);
903        if (!EX(symbol_table)) {
904            zend_rebuild_symbol_table(TSRMLS_C);
905        }
906        ht = &EX(symbol_table)->ht;
907    }
908    return ht;
909}
910
911static zend_always_inline zval *zend_fetch_dimension_address_inner(HashTable *ht, const zval *dim, int dim_type, int type TSRMLS_DC)
912{
913    zval *retval;
914    zend_string *offset_key;
915    zend_ulong hval;
916
917    if (EXPECTED(Z_TYPE_P(dim) == IS_LONG)) {
918        hval = Z_LVAL_P(dim);
919num_index:
920        retval = zend_hash_index_find(ht, hval);
921        if (retval == NULL) {
922            switch (type) {
923                case BP_VAR_R:
924                    zend_error(E_NOTICE,"Undefined offset: " ZEND_ULONG_FMT, hval);
925                    /* break missing intentionally */
926                case BP_VAR_UNSET:
927                case BP_VAR_IS:
928                    retval = &EG(uninitialized_zval);
929                    break;
930                case BP_VAR_RW:
931                    zend_error(E_NOTICE,"Undefined offset: " ZEND_ULONG_FMT, hval);
932                    /* break missing intentionally */
933                case BP_VAR_W:
934                    retval = zend_hash_index_add_new(ht, hval, &EG(uninitialized_zval));
935                    break;
936            }
937        }
938    } else if (EXPECTED(Z_TYPE_P(dim) == IS_STRING)) {
939        offset_key = Z_STR_P(dim);
940        if (dim_type != IS_CONST) {
941            if (ZEND_HANDLE_NUMERIC(offset_key, hval)) {
942                goto num_index;
943            }
944        }
945str_index:
946        retval = zend_hash_find(ht, offset_key);
947        if (retval) {
948            /* support for $GLOBALS[...] */
949            if (UNEXPECTED(Z_TYPE_P(retval) == IS_INDIRECT)) {
950                retval = Z_INDIRECT_P(retval);
951                if (UNEXPECTED(Z_TYPE_P(retval) == IS_UNDEF)) {
952                    switch (type) {
953                        case BP_VAR_R:
954                            zend_error(E_NOTICE, "Undefined index: %s", offset_key->val);
955                            /* break missing intentionally */
956                        case BP_VAR_UNSET:
957                        case BP_VAR_IS:
958                            retval = &EG(uninitialized_zval);
959                            break;
960                        case BP_VAR_RW:
961                            zend_error(E_NOTICE,"Undefined index: %s", offset_key->val);
962                            /* break missing intentionally */
963                        case BP_VAR_W:
964                            ZVAL_NULL(retval);
965                            break;
966                    }
967                }
968            }
969        } else {
970            switch (type) {
971                case BP_VAR_R:
972                    zend_error(E_NOTICE, "Undefined index: %s", offset_key->val);
973                    /* break missing intentionally */
974                case BP_VAR_UNSET:
975                case BP_VAR_IS:
976                    retval = &EG(uninitialized_zval);
977                    break;
978                case BP_VAR_RW:
979                    zend_error(E_NOTICE,"Undefined index: %s", offset_key->val);
980                    /* break missing intentionally */
981                case BP_VAR_W:
982                    retval = zend_hash_add_new(ht, offset_key, &EG(uninitialized_zval));
983                    break;
984            }
985        }
986    } else {
987        switch (Z_TYPE_P(dim)) {
988            case IS_NULL:
989                offset_key = STR_EMPTY_ALLOC();
990                goto str_index;
991            case IS_DOUBLE:
992                hval = zend_dval_to_lval(Z_DVAL_P(dim));
993                goto num_index;
994            case IS_RESOURCE:
995                zend_error(E_STRICT, "Resource ID#%pd used as offset, casting to integer (%pd)", Z_RES_HANDLE_P(dim), Z_RES_HANDLE_P(dim));
996                hval = Z_RES_HANDLE_P(dim);
997                goto num_index;
998            case IS_FALSE:
999                hval = 0;
1000                goto num_index;
1001            case IS_TRUE:
1002                hval = 1;
1003                goto num_index;
1004            default:
1005                zend_error(E_WARNING, "Illegal offset type");
1006                retval = (type == BP_VAR_W || type == BP_VAR_RW) ?
1007                    &EG(error_zval) : &EG(uninitialized_zval);
1008        }
1009    }
1010    return retval;
1011}
1012
1013static zend_always_inline zval *zend_fetch_dimension_address(zval *result, zval *container_ptr, zval *dim, int dim_type, int type, int is_ref, int allow_str_offset TSRMLS_DC)
1014{
1015    zval *retval;
1016    zval *container = container_ptr;
1017
1018    ZVAL_DEREF(container);
1019    if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
1020        SEPARATE_ARRAY(container);
1021fetch_from_array:
1022        if (dim == NULL) {
1023            retval = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval));
1024            if (UNEXPECTED(retval == NULL)) {
1025                zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied");
1026                retval = &EG(error_zval);
1027            }
1028        } else {
1029            retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, dim_type, type TSRMLS_CC);
1030        }
1031        if (is_ref) {
1032            ZVAL_MAKE_REF(retval);
1033        }
1034        ZVAL_INDIRECT(result, retval);
1035    } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) {
1036        zend_long offset;
1037
1038        if (type != BP_VAR_UNSET && UNEXPECTED(Z_STRLEN_P(container) == 0)) {
1039            zval_dtor(container);
1040convert_to_array:
1041            ZVAL_NEW_ARR(container);
1042            zend_hash_init(Z_ARRVAL_P(container), 8, NULL, ZVAL_PTR_DTOR, 0);
1043            goto fetch_from_array;
1044        }
1045
1046        if (dim == NULL) {
1047            zend_error_noreturn(E_ERROR, "[] operator not supported for strings");
1048        }
1049
1050        if (UNEXPECTED(Z_TYPE_P(dim) != IS_LONG)) {
1051            switch(Z_TYPE_P(dim)) {
1052                case IS_STRING:
1053                    if (IS_LONG == is_numeric_string(Z_STRVAL_P(dim), Z_STRLEN_P(dim), NULL, NULL, -1)) {
1054                        break;
1055                    }
1056                    if (type != BP_VAR_UNSET) {
1057                        zend_error(E_WARNING, "Illegal string offset '%s'", Z_STRVAL_P(dim));
1058                    }
1059                    break;
1060                case IS_DOUBLE:
1061                case IS_NULL:
1062                case IS_FALSE:
1063                case IS_TRUE:
1064                    zend_error(E_NOTICE, "String offset cast occurred");
1065                    break;
1066                default:
1067                    zend_error(E_WARNING, "Illegal offset type");
1068                    break;
1069            }
1070
1071            offset = zval_get_long(dim);
1072        } else {
1073            offset = Z_LVAL_P(dim);
1074        }
1075
1076        if (allow_str_offset) {
1077            if (Z_REFCOUNTED_P(container)) {
1078                if (Z_REFCOUNT_P(container) > 1) {
1079                    Z_DELREF_P(container);
1080                    zval_copy_ctor_func(container);
1081                }
1082                Z_ADDREF_P(container);
1083            }
1084            ZVAL_LONG(result, offset);
1085            return container; /* assignment to string offset */
1086        } else {
1087            ZVAL_INDIRECT(result, NULL); /* wrong string offset */
1088        }
1089    } else if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
1090        if (!Z_OBJ_HT_P(container)->read_dimension) {
1091            zend_error_noreturn(E_ERROR, "Cannot use object as array");
1092        } else {
1093            retval = Z_OBJ_HT_P(container)->read_dimension(container, dim, type, result TSRMLS_CC);
1094
1095            if (UNEXPECTED(retval == &EG(uninitialized_zval))) {
1096                zend_class_entry *ce = Z_OBJCE_P(container);
1097
1098                ZVAL_NULL(result);
1099                zend_error(E_NOTICE, "Indirect modification of overloaded element of %s has no effect", ce->name->val);
1100            } else if (EXPECTED(retval && Z_TYPE_P(retval) != IS_UNDEF)) {
1101                if (!Z_ISREF_P(retval)) {
1102                    if (Z_REFCOUNTED_P(retval) &&
1103                        Z_REFCOUNT_P(retval) > 1) {
1104                        if (Z_TYPE_P(retval) != IS_OBJECT) {
1105                            Z_DELREF_P(retval);
1106                            ZVAL_DUP(result, retval);
1107                            retval = result;
1108                        } else {
1109                            ZVAL_COPY(result, retval);
1110                            retval = result;
1111                        }
1112                    }
1113                    if (Z_TYPE_P(retval) != IS_OBJECT) {
1114                        zend_class_entry *ce = Z_OBJCE_P(container);
1115                        zend_error(E_NOTICE, "Indirect modification of overloaded element of %s has no effect", ce->name->val);
1116                    }
1117                }
1118                if (result != retval) {
1119                    if (is_ref) {
1120                        ZVAL_MAKE_REF(retval);
1121                    }
1122                    ZVAL_INDIRECT(result, retval);
1123                }
1124            } else {
1125                ZVAL_INDIRECT(result, &EG(error_zval));
1126            }
1127        }
1128    } else if (EXPECTED(Z_TYPE_P(container) == IS_NULL)) {
1129        if (UNEXPECTED(container == &EG(error_zval))) {
1130            ZVAL_INDIRECT(result, &EG(error_zval));
1131        } else if (type != BP_VAR_UNSET) {
1132            goto convert_to_array;
1133        } else {
1134            /* for read-mode only */
1135            ZVAL_NULL(result);
1136        }
1137    } else {
1138        if (type != BP_VAR_UNSET &&
1139            Z_TYPE_P(container) == IS_FALSE) {
1140            goto convert_to_array;
1141        }
1142        if (type == BP_VAR_UNSET) {
1143            zend_error(E_WARNING, "Cannot unset offset in a non-array variable");
1144            ZVAL_NULL(result);
1145        } else {
1146            zend_error(E_WARNING, "Cannot use a scalar value as an array");
1147            ZVAL_INDIRECT(result, &EG(error_zval));
1148        }
1149    }
1150    return NULL; /* not an assignment to string offset */
1151}
1152
1153static zend_never_inline void zend_fetch_dimension_address_W(zval *result, zval *container_ptr, zval *dim, int dim_type TSRMLS_DC)
1154{
1155    zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_W, 0, 0 TSRMLS_CC);
1156}
1157
1158static zend_never_inline zval *zend_fetch_dimension_address_W_str(zval *result, zval *container_ptr, zval *dim, int dim_type TSRMLS_DC)
1159{
1160    return zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_W, 0, 1 TSRMLS_CC);
1161}
1162
1163static zend_never_inline void zend_fetch_dimension_address_W_ref(zval *result, zval *container_ptr, zval *dim, int dim_type TSRMLS_DC)
1164{
1165    zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_W, 1, 0 TSRMLS_CC);
1166}
1167
1168static zend_never_inline void zend_fetch_dimension_address_RW(zval *result, zval *container_ptr, zval *dim, int dim_type TSRMLS_DC)
1169{
1170    zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_RW, 0, 0 TSRMLS_CC);
1171}
1172
1173static zend_never_inline void zend_fetch_dimension_address_UNSET(zval *result, zval *container_ptr, zval *dim, int dim_type TSRMLS_DC)
1174{
1175    zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_UNSET, 0, 0 TSRMLS_CC);
1176}
1177
1178static zend_always_inline void zend_fetch_dimension_address_read(zval *result, zval *container, zval *dim, int dim_type, int type TSRMLS_DC)
1179{
1180    zval *retval;
1181
1182    ZVAL_DEREF(container);
1183    if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
1184        retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, dim_type, type TSRMLS_CC);
1185        ZVAL_COPY(result, retval);
1186    } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) {
1187        zend_long offset;
1188
1189        if (UNEXPECTED(Z_TYPE_P(dim) != IS_LONG)) {
1190            switch(Z_TYPE_P(dim)) {
1191                /* case IS_LONG: */
1192                case IS_STRING:
1193                    if (IS_LONG == is_numeric_string(Z_STRVAL_P(dim), Z_STRLEN_P(dim), NULL, NULL, -1)) {
1194                        break;
1195                    }
1196                    if (type != BP_VAR_IS) {
1197                        zend_error(E_WARNING, "Illegal string offset '%s'", Z_STRVAL_P(dim));
1198                    }
1199                    break;
1200                case IS_DOUBLE:
1201                case IS_NULL:
1202                case IS_FALSE:
1203                case IS_TRUE:
1204                    if (type != BP_VAR_IS) {
1205                        zend_error(E_NOTICE, "String offset cast occurred");
1206                    }
1207                    break;
1208                default:
1209                    zend_error(E_WARNING, "Illegal offset type");
1210                    break;
1211            }
1212
1213            offset = zval_get_long(dim);
1214        } else {
1215            offset = Z_LVAL_P(dim);
1216        }
1217
1218        if (UNEXPECTED(offset < 0) || UNEXPECTED(Z_STRLEN_P(container) <= (size_t)offset)) {
1219            if (type != BP_VAR_IS) {
1220                zend_error(E_NOTICE, "Uninitialized string offset: %pd", offset);
1221            }
1222            ZVAL_EMPTY_STRING(result);
1223        } else {
1224            zend_uchar c = (zend_uchar)Z_STRVAL_P(container)[offset];
1225
1226            if (CG(one_char_string)[c]) {
1227                ZVAL_INTERNED_STR(result, CG(one_char_string)[c]);
1228            } else {
1229                ZVAL_NEW_STR(result, zend_string_init(Z_STRVAL_P(container) + offset, 1, 0));
1230            }
1231        }
1232    } else if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
1233        if (!Z_OBJ_HT_P(container)->read_dimension) {
1234            zend_error_noreturn(E_ERROR, "Cannot use object as array");
1235        } else {
1236            retval = Z_OBJ_HT_P(container)->read_dimension(container, dim, type, result TSRMLS_CC);
1237
1238            if (result) {
1239                if (retval) {
1240                    if (result != retval) {
1241                        ZVAL_COPY(result, retval);
1242                    }
1243                } else {
1244                    ZVAL_NULL(result);
1245                }
1246            }
1247        }
1248    } else {
1249        ZVAL_NULL(result);
1250    }
1251}
1252
1253static zend_never_inline void zend_fetch_dimension_address_read_R(zval *result, zval *container, zval *dim, int dim_type TSRMLS_DC)
1254{
1255    zend_fetch_dimension_address_read(result, container, dim, dim_type, BP_VAR_R TSRMLS_CC);
1256}
1257
1258static zend_never_inline void zend_fetch_dimension_address_read_IS(zval *result, zval *container, zval *dim, int dim_type TSRMLS_DC)
1259{
1260    zend_fetch_dimension_address_read(result, container, dim, dim_type, BP_VAR_IS TSRMLS_CC);
1261}
1262
1263ZEND_API void zend_fetch_dimension_by_zval(zval *result, zval *container, zval *dim TSRMLS_DC)
1264{
1265    zend_fetch_dimension_address_read_R(result, container, dim, IS_TMP_VAR TSRMLS_CC);
1266}
1267
1268static void zend_fetch_property_address(zval *result, zval *container_ptr, zval *prop_ptr, void **cache_slot, int type, int is_ref TSRMLS_DC)
1269{
1270    zval *container = container_ptr;
1271
1272    ZVAL_DEREF(container);
1273    if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
1274        if (UNEXPECTED(container == &EG(error_zval))) {
1275            ZVAL_INDIRECT(result, &EG(error_zval));
1276            return;
1277        }
1278
1279        /* this should modify object only if it's empty */
1280        if (type != BP_VAR_UNSET &&
1281            EXPECTED((Z_TYPE_P(container) == IS_NULL ||
1282              Z_TYPE_P(container) == IS_FALSE ||
1283              (Z_TYPE_P(container) == IS_STRING && Z_STRLEN_P(container)==0)))) {
1284            zval_ptr_dtor_nogc(container);
1285            object_init(container);
1286        } else {
1287            zend_error(E_WARNING, "Attempt to modify property of non-object");
1288            ZVAL_INDIRECT(result, &EG(error_zval));
1289            return;
1290        }
1291    }
1292
1293    if (EXPECTED(Z_OBJ_HT_P(container)->get_property_ptr_ptr)) {
1294        zval *ptr = Z_OBJ_HT_P(container)->get_property_ptr_ptr(container, prop_ptr, type, cache_slot TSRMLS_CC);
1295        if (NULL == ptr) {
1296            if (Z_OBJ_HT_P(container)->read_property &&
1297                (ptr = Z_OBJ_HT_P(container)->read_property(container, prop_ptr, type, cache_slot, result TSRMLS_CC)) != NULL) {
1298                if (ptr != result) {
1299                    if (is_ref && ptr != &EG(uninitialized_zval)) {
1300                        ZVAL_MAKE_REF(ptr);
1301                    }
1302                    ZVAL_INDIRECT(result, ptr);
1303                }
1304            } else {
1305                zend_error_noreturn(E_ERROR, "Cannot access undefined property for object with overloaded property access");
1306            }
1307        } else {
1308            if (is_ref) {
1309                ZVAL_MAKE_REF(ptr);
1310            }
1311            ZVAL_INDIRECT(result, ptr);
1312        }
1313    } else if (EXPECTED(Z_OBJ_HT_P(container)->read_property)) {
1314        zval *ptr = Z_OBJ_HT_P(container)->read_property(container, prop_ptr, type, cache_slot, result TSRMLS_CC);
1315        if (ptr != result) {
1316            if (is_ref && ptr != &EG(uninitialized_zval)) {
1317                ZVAL_MAKE_REF(ptr);
1318            }
1319            ZVAL_INDIRECT(result, ptr);
1320        }
1321    } else {
1322        zend_error(E_WARNING, "This object doesn't support property references");
1323        ZVAL_INDIRECT(result, &EG(error_zval));
1324    }
1325}
1326
1327static inline zend_brk_cont_element* zend_brk_cont(int nest_levels, int array_offset, const zend_op_array *op_array, const zend_execute_data *execute_data TSRMLS_DC)
1328{
1329    int original_nest_levels = nest_levels;
1330    zend_brk_cont_element *jmp_to;
1331
1332    do {
1333        if (array_offset==-1) {
1334            zend_error_noreturn(E_ERROR, "Cannot break/continue %d level%s", original_nest_levels, (original_nest_levels == 1) ? "" : "s");
1335        }
1336        jmp_to = &op_array->brk_cont_array[array_offset];
1337        if (nest_levels>1) {
1338            zend_op *brk_opline = &op_array->opcodes[jmp_to->brk];
1339
1340            if (brk_opline->opcode == ZEND_SWITCH_FREE) {
1341                if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
1342                    zval_ptr_dtor(EX_VAR(brk_opline->op1.var));
1343                }
1344            } else if (brk_opline->opcode == ZEND_FREE) {
1345                if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
1346                    zval_dtor(EX_VAR(brk_opline->op1.var));
1347                }
1348            }
1349        }
1350        array_offset = jmp_to->parent;
1351    } while (--nest_levels > 0);
1352    return jmp_to;
1353}
1354
1355#if ZEND_INTENSIVE_DEBUGGING
1356
1357#define CHECK_SYMBOL_TABLES()                                                   \
1358    zend_hash_apply(&EG(symbol_table), zend_check_symbol TSRMLS_CC);            \
1359    if (&EG(symbol_table)!=EX(symbol_table)) {                          \
1360        zend_hash_apply(EX(symbol_table), zend_check_symbol TSRMLS_CC); \
1361    }
1362
1363static int zend_check_symbol(zval *pz TSRMLS_DC)
1364{
1365    if (Z_TYPE_P(pz) == IS_INDIRECT) {
1366        pz = Z_INDIRECT_P(pz);
1367    }
1368    if (Z_TYPE_P(pz) > 10) {
1369        fprintf(stderr, "Warning!  %x has invalid type!\n", *pz);
1370/* See http://support.microsoft.com/kb/190351 */
1371#ifdef PHP_WIN32
1372        fflush(stderr);
1373#endif
1374    } else if (Z_TYPE_P(pz) == IS_ARRAY) {
1375        zend_hash_apply(Z_ARRVAL_P(pz), zend_check_symbol TSRMLS_CC);
1376    } else if (Z_TYPE_P(pz) == IS_OBJECT) {
1377        /* OBJ-TBI - doesn't support new object model! */
1378        zend_hash_apply(Z_OBJPROP_P(pz), zend_check_symbol TSRMLS_CC);
1379    }
1380
1381    return 0;
1382}
1383
1384
1385#else
1386#define CHECK_SYMBOL_TABLES()
1387#endif
1388
1389ZEND_API opcode_handler_t *zend_opcode_handlers;
1390
1391ZEND_API void execute_internal(zend_execute_data *execute_data, zval *return_value TSRMLS_DC)
1392{
1393    execute_data->func->internal_function.handler(execute_data->num_args, return_value TSRMLS_CC);
1394}
1395
1396void zend_clean_and_cache_symbol_table(zend_array *symbol_table TSRMLS_DC) /* {{{ */
1397{
1398    if (EG(symtable_cache_ptr) >= EG(symtable_cache_limit)) {
1399        zend_hash_destroy(&symbol_table->ht);
1400        FREE_HASHTABLE(symbol_table);
1401    } else {
1402        /* clean before putting into the cache, since clean
1403           could call dtors, which could use cached hash */
1404        zend_hash_clean(&symbol_table->ht);
1405        *(++EG(symtable_cache_ptr)) = symbol_table;
1406    }
1407}
1408/* }}} */
1409
1410static zend_always_inline void i_free_compiled_variables(zend_execute_data *execute_data TSRMLS_DC) /* {{{ */
1411{
1412    if (EXPECTED(EX(func)->op_array.last_var > 0)) {
1413        zval *cv = EX_VAR_NUM(0);
1414        zval *end = cv + EX(func)->op_array.last_var;
1415        do {
1416            zval_ptr_dtor(cv);
1417            cv++;
1418        } while (cv != end);
1419    }
1420}
1421/* }}} */
1422
1423void zend_free_compiled_variables(zend_execute_data *execute_data TSRMLS_DC) /* {{{ */
1424{
1425    i_free_compiled_variables(execute_data TSRMLS_CC);
1426}
1427/* }}} */
1428
1429/*
1430 * Stack Frame Layout (the whole stack frame is allocated at once)
1431 * ==================
1432 *
1433 *                             +========================================+
1434 * EG(current_execute_data) -> | zend_execute_data                      |
1435 *                             +----------------------------------------+
1436 *     EX_CV_NUM(0) ---------> | VAR[0] = ARG[1]                        |
1437 *                             | ...                                    |
1438 *                             | VAR[op_array->num_args-1] = ARG[N]     |
1439 *                             | ...                                    |
1440 *                             | VAR[op_array->last_var-1]              |
1441 *                             | VAR[op_array->last_var] = TMP[0]       |
1442 *                             | ...                                    |
1443 *                             | VAR[op_array->last_var+op_array->T-1]  |
1444 *                             | ARG[N+1] (extra_args)                  |
1445 *                             | ...                                    |
1446 *                             +----------------------------------------+
1447 */
1448
1449static zend_always_inline void i_init_func_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value, vm_frame_kind frame_kind TSRMLS_DC) /* {{{ */
1450{
1451    uint32_t first_extra_arg, num_args;
1452    ZEND_ASSERT(EX(func) == (zend_function*)op_array);
1453    ZEND_ASSERT(EX(object) == Z_OBJ(EG(This)));
1454
1455    EX(opline) = op_array->opcodes;
1456    EX(call) = NULL;
1457    EX(frame_kind) = frame_kind;
1458    EX(return_value) = return_value;
1459    EX(scope) = EG(scope);
1460    EX(delayed_exception) = NULL;
1461    ZVAL_UNDEF(&EX(old_error_reporting));
1462
1463    /* Handle arguments */
1464    first_extra_arg = op_array->num_args;
1465    if (UNEXPECTED((op_array->fn_flags & ZEND_ACC_VARIADIC) != 0)) {
1466        first_extra_arg--;
1467    }
1468    num_args = EX(num_args);
1469    if (UNEXPECTED(num_args > first_extra_arg)) {
1470        zval *end, *src, *dst;
1471
1472        if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) {
1473            /* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */
1474            EX(opline) += first_extra_arg;
1475        }
1476
1477        /* move extra args into separate array after all CV and TMP vars */
1478        end = EX_VAR_NUM(first_extra_arg - 1);
1479        src = end + (num_args - first_extra_arg);
1480        dst = src + (op_array->last_var + op_array->T - first_extra_arg);
1481        if (EXPECTED(src != dst)) {
1482            do {
1483                ZVAL_COPY_VALUE(dst, src);
1484                ZVAL_UNDEF(src);
1485                src--;
1486                dst--;
1487            } while (src != end);
1488        }
1489    } else if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) {
1490        /* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */
1491        EX(opline) += num_args;
1492    }
1493
1494    /* Initialize CV variables (skip arguments) */
1495    if (EXPECTED(num_args < op_array->last_var)) {
1496        zval *var = EX_VAR_NUM(num_args);
1497        zval *end = EX_VAR_NUM(op_array->last_var);
1498
1499        do {
1500            ZVAL_UNDEF(var);
1501            var++;
1502        } while (var != end);
1503    }
1504
1505    if (op_array->this_var != -1 && EX(object)) {
1506        ZVAL_OBJ(EX_VAR(op_array->this_var), EX(object));
1507        GC_REFCOUNT(EX(object))++;
1508    }
1509
1510    if (!op_array->run_time_cache && op_array->last_cache_slot) {
1511        op_array->run_time_cache = zend_arena_calloc(&CG(arena), op_array->last_cache_slot, sizeof(void*));
1512    }
1513    EX(run_time_cache) = op_array->run_time_cache;
1514
1515    EG(current_execute_data) = execute_data;
1516}
1517/* }}} */
1518
1519static zend_always_inline void i_init_code_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value, vm_frame_kind frame_kind TSRMLS_DC) /* {{{ */
1520{
1521    ZEND_ASSERT(EX(func) == (zend_function*)op_array);
1522    ZEND_ASSERT(EX(object) == Z_OBJ(EG(This)));
1523
1524    EX(opline) = op_array->opcodes;
1525    EX(call) = NULL;
1526    EX(frame_kind) = frame_kind;
1527    EX(return_value) = return_value;
1528    EX(scope) = EG(scope);
1529    EX(delayed_exception) = NULL;
1530    ZVAL_UNDEF(&EX(old_error_reporting));
1531
1532    zend_attach_symbol_table(execute_data);
1533
1534    if (!op_array->run_time_cache && op_array->last_cache_slot) {
1535        op_array->run_time_cache = ecalloc(op_array->last_cache_slot, sizeof(void*));
1536    }
1537    EX(run_time_cache) = op_array->run_time_cache;
1538
1539    EG(current_execute_data) = execute_data;
1540}
1541/* }}} */
1542
1543static zend_always_inline void i_init_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value, vm_frame_kind frame_kind TSRMLS_DC) /* {{{ */
1544{
1545    ZEND_ASSERT(EX(func) == (zend_function*)op_array);
1546    ZEND_ASSERT(EX(object) == Z_OBJ(EG(This)));
1547
1548    EX(opline) = op_array->opcodes;
1549    EX(call) = NULL;
1550    EX(frame_kind) = frame_kind;
1551    EX(return_value) = return_value;
1552    EX(scope) = EG(scope);
1553    EX(delayed_exception) = NULL;
1554    ZVAL_UNDEF(&EX(old_error_reporting));
1555
1556    if (UNEXPECTED(EX(symbol_table) != NULL)) {
1557        zend_attach_symbol_table(execute_data);
1558    } else {
1559        uint32_t first_extra_arg, num_args;
1560
1561        /* Handle arguments */
1562        first_extra_arg = op_array->num_args;
1563        if (UNEXPECTED((op_array->fn_flags & ZEND_ACC_VARIADIC) != 0)) {
1564            first_extra_arg--;
1565        }
1566        num_args = EX(num_args);
1567        if (UNEXPECTED(num_args > first_extra_arg)) {
1568            zval *end, *src, *dst;
1569
1570            if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) {
1571                /* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */
1572                EX(opline) += first_extra_arg;
1573            }
1574
1575            /* move extra args into separate array after all CV and TMP vars */
1576            end = EX_VAR_NUM(first_extra_arg - 1);
1577            src = end + (num_args - first_extra_arg);
1578            dst = src + (op_array->last_var + op_array->T - first_extra_arg);
1579            if (EXPECTED(src != dst)) {
1580                do {
1581                    ZVAL_COPY_VALUE(dst, src);
1582                    ZVAL_UNDEF(src);
1583                    src--;
1584                    dst--;
1585                } while (src != end);
1586            }
1587        } else if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) {
1588            /* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */
1589            EX(opline) += num_args;
1590        }
1591
1592        /* Initialize CV variables (skip arguments) */
1593        if (EXPECTED(num_args < op_array->last_var)) {
1594            zval *var = EX_VAR_NUM(num_args);
1595            zval *end = EX_VAR_NUM(op_array->last_var);
1596
1597            do {
1598                ZVAL_UNDEF(var);
1599                var++;
1600            } while (var != end);
1601        }
1602
1603        if (op_array->this_var != -1 && EX(object)) {
1604            ZVAL_OBJ(EX_VAR(op_array->this_var), EX(object));
1605            GC_REFCOUNT(EX(object))++;
1606        }
1607    }
1608
1609    if (!op_array->run_time_cache && op_array->last_cache_slot) {
1610        if (op_array->function_name) {
1611            op_array->run_time_cache = zend_arena_calloc(&CG(arena), op_array->last_cache_slot, sizeof(void*));
1612        } else {
1613            op_array->run_time_cache = ecalloc(op_array->last_cache_slot, sizeof(void*));
1614        }
1615    }
1616    EX(run_time_cache) = op_array->run_time_cache;
1617
1618    EG(current_execute_data) = execute_data;
1619}
1620/* }}} */
1621
1622ZEND_API zend_execute_data *zend_create_generator_execute_data(zend_execute_data *call, zend_op_array *op_array, zval *return_value TSRMLS_DC) /* {{{ */
1623{
1624    /*
1625     * Normally the execute_data is allocated on the VM stack (because it does
1626     * not actually do any allocation and thus is faster). For generators
1627     * though this behavior would be suboptimal, because the (rather large)
1628     * structure would have to be copied back and forth every time execution is
1629     * suspended or resumed. That's why for generators the execution context
1630     * is allocated using a separate VM stack, thus allowing to save and
1631     * restore it simply by replacing a pointer.
1632     */
1633    zend_execute_data *execute_data;
1634    uint32_t num_args = call->num_args;
1635
1636    EG(argument_stack) = zend_vm_stack_new_page(
1637        MAX(ZEND_VM_STACK_PAGE_SIZE,
1638            ZEND_CALL_FRAME_SLOT + MAX(op_array->last_var + op_array->T, num_args)));
1639    EG(argument_stack)->prev = NULL;
1640
1641    execute_data = zend_vm_stack_push_call_frame(
1642        (zend_function*)op_array,
1643        num_args,
1644        call->flags,
1645        call->called_scope,
1646        call->object,
1647        NULL TSRMLS_CC);
1648    EX(num_args) = num_args;
1649
1650    /* copy arguments */
1651    if (num_args > 0) {
1652        zval *arg_src = ZEND_CALL_ARG(call, 1);
1653        zval *arg_dst = ZEND_CALL_ARG(execute_data, 1);
1654        uint32_t i;
1655
1656        for (i = 0; i < num_args; i++) {
1657            ZVAL_COPY_VALUE(arg_dst + i, arg_src + i);
1658        }
1659    }
1660
1661    EX(symbol_table) = NULL;
1662
1663    i_init_func_execute_data(execute_data, op_array, return_value, VM_FRAME_TOP_FUNCTION TSRMLS_CC);
1664
1665    return execute_data;
1666}
1667/* }}} */
1668
1669ZEND_API void zend_init_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value, vm_frame_kind frame_kind TSRMLS_DC) /* {{{ */
1670{
1671    EX(prev_execute_data) = EG(current_execute_data);
1672    i_init_execute_data(execute_data, op_array, return_value, frame_kind TSRMLS_CC);
1673}
1674/* }}} */
1675
1676static zend_always_inline zend_bool zend_is_by_ref_func_arg_fetch(const zend_op *opline, zend_execute_data *call TSRMLS_DC) /* {{{ */
1677{
1678    uint32_t arg_num = opline->extended_value & ZEND_FETCH_ARG_MASK;
1679    return ARG_SHOULD_BE_SENT_BY_REF(call->func, arg_num);
1680}
1681/* }}} */
1682
1683static zend_execute_data *zend_vm_stack_copy_call_frame(zend_execute_data *call, uint32_t passed_args, uint32_t additional_args TSRMLS_DC) /* {{{ */
1684{
1685    zend_execute_data *new_call;
1686    int used_stack = (EG(argument_stack)->top - (zval*)call) + additional_args;
1687
1688    /* copy call frame into new stack segment */
1689    zend_vm_stack_extend(used_stack TSRMLS_CC);
1690    new_call = (zend_execute_data*)EG(argument_stack)->top;
1691    EG(argument_stack)->top += used_stack;
1692    *new_call = *call;
1693    if (passed_args) {
1694        zval *src = ZEND_CALL_ARG(call, 1);
1695        zval *dst = ZEND_CALL_ARG(new_call, 1);
1696        do {
1697            ZVAL_COPY_VALUE(dst, src);
1698            passed_args--;
1699            src++;
1700            dst++;
1701        } while (passed_args);
1702    }
1703
1704    /* delete old call_frame from previous stack segment */
1705    EG(argument_stack)->prev->top = (zval*)call;
1706
1707    /* delete previous stack segment if it becames empty */
1708    if (UNEXPECTED(EG(argument_stack)->prev->top == ZEND_VM_STACK_ELEMETS(EG(argument_stack)->prev))) {
1709        zend_vm_stack r = EG(argument_stack)->prev;
1710
1711        EG(argument_stack)->prev = r->prev;
1712        efree(r);
1713    }
1714
1715    return new_call;
1716}
1717/* }}} */
1718
1719static zend_always_inline void zend_vm_stack_extend_call_frame(zend_execute_data **call, uint32_t passed_args, uint32_t additional_args TSRMLS_DC) /* {{{ */
1720{
1721    if (EXPECTED(EG(argument_stack)->end - EG(argument_stack)->top > additional_args)) {
1722        EG(argument_stack)->top += additional_args;
1723    } else {
1724        *call = zend_vm_stack_copy_call_frame(*call, passed_args, additional_args TSRMLS_CC);
1725    }
1726}
1727/* }}} */
1728
1729#define ZEND_VM_NEXT_OPCODE() \
1730    CHECK_SYMBOL_TABLES() \
1731    ZEND_VM_INC_OPCODE(); \
1732    ZEND_VM_CONTINUE()
1733
1734#define ZEND_VM_SET_OPCODE(new_op) \
1735    CHECK_SYMBOL_TABLES() \
1736    OPLINE = new_op
1737
1738#define ZEND_VM_SET_RELATIVE_OPCODE(opline, offset) \
1739    CHECK_SYMBOL_TABLES() \
1740    OPLINE = ((zend_op*)(((char*)opline)+(offset)))
1741
1742#define ZEND_VM_JMP(new_op) \
1743    if (EXPECTED(!EG(exception))) { \
1744        ZEND_VM_SET_OPCODE(new_op); \
1745    } else { \
1746        LOAD_OPLINE(); \
1747    } \
1748    ZEND_VM_CONTINUE()
1749
1750#define ZEND_VM_INC_OPCODE() \
1751    OPLINE++
1752
1753#ifdef __GNUC__
1754# define ZEND_VM_GUARD(name) __asm__("#" #name)
1755#else
1756# define ZEND_VM_GUARD(name)
1757#endif
1758
1759#include "zend_vm_execute.h"
1760
1761ZEND_API int zend_set_user_opcode_handler(zend_uchar opcode, user_opcode_handler_t handler)
1762{
1763    if (opcode != ZEND_USER_OPCODE) {
1764        if (handler == NULL) {
1765            /* restore the original handler */
1766            zend_user_opcodes[opcode] = opcode;
1767        } else {
1768            zend_user_opcodes[opcode] = ZEND_USER_OPCODE;
1769        }
1770        zend_user_opcode_handlers[opcode] = handler;
1771        return SUCCESS;
1772    }
1773    return FAILURE;
1774}
1775
1776ZEND_API user_opcode_handler_t zend_get_user_opcode_handler(zend_uchar opcode)
1777{
1778    return zend_user_opcode_handlers[opcode];
1779}
1780
1781ZEND_API zval *zend_get_zval_ptr(int op_type, const znode_op *node, const zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC) {
1782    return get_zval_ptr(op_type, node, execute_data, should_free, type);
1783}
1784
1785/*
1786 * Local variables:
1787 * tab-width: 4
1788 * c-basic-offset: 4
1789 * indent-tabs-mode: t
1790 * End:
1791 */
1792