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