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