1/*
2   +----------------------------------------------------------------------+
3   | Zend Engine                                                          |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 1998-2015 Zend Technologies Ltd. (http://www.zend.com) |
6   +----------------------------------------------------------------------+
7   | This source file is subject to version 2.00 of the Zend license,     |
8   | that is bundled with this package in the file LICENSE, and is        |
9   | available through the world-wide-web at the following url:           |
10   | http://www.zend.com/license/2_00.txt.                                |
11   | If you did not receive a copy of the Zend license and are unable to  |
12   | obtain it through the world-wide-web, please send a note to          |
13   | license@zend.com so we can mail you a copy immediately.              |
14   +----------------------------------------------------------------------+
15   | Authors: Andi Gutmans <andi@zend.com>                                |
16   |          Zeev Suraski <zeev@zend.com>                                |
17   +----------------------------------------------------------------------+
18*/
19
20/* $Id$ */
21
22#define ZEND_INTENSIVE_DEBUGGING 0
23
24#include <stdio.h>
25#include <signal.h>
26
27#include "zend.h"
28#include "zend_compile.h"
29#include "zend_execute.h"
30#include "zend_API.h"
31#include "zend_ptr_stack.h"
32#include "zend_constants.h"
33#include "zend_extensions.h"
34#include "zend_ini.h"
35#include "zend_exceptions.h"
36#include "zend_interfaces.h"
37#include "zend_closures.h"
38#include "zend_generators.h"
39#include "zend_vm.h"
40#include "zend_dtrace.h"
41#include "zend_inheritance.h"
42
43/* Virtual current working directory support */
44#include "zend_virtual_cwd.h"
45
46#define _CONST_CODE  0
47#define _TMP_CODE    1
48#define _VAR_CODE    2
49#define _UNUSED_CODE 3
50#define _CV_CODE     4
51
52typedef int (ZEND_FASTCALL *incdec_t)(zval *);
53
54#define get_zval_ptr(op_type, node, ex, should_free, type) _get_zval_ptr(op_type, node, ex, should_free, type)
55#define get_zval_ptr_deref(op_type, node, ex, should_free, type) _get_zval_ptr_deref(op_type, node, ex, should_free, type)
56#define get_zval_ptr_undef(op_type, node, ex, should_free, type) _get_zval_ptr_undef(op_type, node, ex, should_free, type)
57#define get_zval_ptr_ptr(op_type, node, ex, should_free, type) _get_zval_ptr_ptr(op_type, node, ex, should_free, type)
58#define get_zval_ptr_ptr_undef(op_type, node, ex, should_free, type) _get_zval_ptr_ptr(op_type, node, ex, should_free, type)
59#define get_obj_zval_ptr(op_type, node, ex, should_free, type) _get_obj_zval_ptr(op_type, node, ex, should_free, type)
60#define get_obj_zval_ptr_undef(op_type, node, ex, should_free, type) _get_obj_zval_ptr_undef(op_type, node, ex, should_free, type)
61#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)
62
63/* Prototypes */
64static void zend_extension_statement_handler(const zend_extension *extension, zend_op_array *op_array);
65static void zend_extension_fcall_begin_handler(const zend_extension *extension, zend_op_array *op_array);
66static void zend_extension_fcall_end_handler(const zend_extension *extension, zend_op_array *op_array);
67
68#define RETURN_VALUE_USED(opline) (!((opline)->result_type & EXT_TYPE_UNUSED))
69
70static ZEND_FUNCTION(pass)
71{
72}
73
74static const zend_internal_function zend_pass_function = {
75    ZEND_INTERNAL_FUNCTION, /* type              */
76    {0, 0, 0},              /* arg_flags         */
77    0,                      /* fn_flags          */
78    NULL,                   /* name              */
79    NULL,                   /* scope             */
80    NULL,                   /* prototype         */
81    0,                      /* num_args          */
82    0,                      /* required_num_args */
83    NULL,                   /* arg_info          */
84    ZEND_FN(pass),          /* handler           */
85    NULL                    /* module            */
86};
87
88#undef zval_ptr_dtor
89#define zval_ptr_dtor(zv) i_zval_ptr_dtor(zv ZEND_FILE_LINE_CC)
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, check_null) do {       \
95    zval *__zv = (zv);                              \
96    if (Z_TYPE_P(__zv) == IS_INDIRECT) {            \
97        if (!(check_null) || Z_INDIRECT_P(__zv)) {  \
98            ZVAL_COPY(__zv, Z_INDIRECT_P(__zv));    \
99        }                                           \
100    }                                               \
101} while (0)
102
103#define FREE_OP(should_free) \
104    if (should_free) { \
105        zval_ptr_dtor_nogc(should_free); \
106    }
107
108#define FREE_UNFETCHED_OP(type, var) \
109    if ((type) & (IS_TMP_VAR|IS_VAR)) { \
110        zval_ptr_dtor_nogc(EX_VAR(var)); \
111    }
112
113#define FREE_OP_VAR_PTR(should_free) \
114    if (should_free) { \
115        zval_ptr_dtor_nogc(should_free); \
116    }
117
118/* End of zend_execute_locks.h */
119
120#define CV_DEF_OF(i) (EX(func)->op_array.vars[i])
121
122#define CTOR_CALL_BIT    0x1
123#define CTOR_USED_BIT    0x2
124
125#define IS_CTOR_CALL(ce) (((zend_uintptr_t)(ce)) & CTOR_CALL_BIT)
126#define IS_CTOR_USED(ce) (((zend_uintptr_t)(ce)) & CTOR_USED_BIT)
127
128#define ENCODE_CTOR(ce, used) \
129    ((zend_class_entry*)(((zend_uintptr_t)(ce)) | CTOR_CALL_BIT | ((used) ? CTOR_USED_BIT : 0)))
130#define DECODE_CTOR(ce) \
131    ((zend_class_entry*)(((zend_uintptr_t)(ce)) & ~(CTOR_CALL_BIT|CTOR_USED_BIT)))
132
133#define ZEND_VM_MAIN_STACK_PAGE_SLOTS (16 * 1024) /* should be a power of 2 */
134#define ZEND_VM_GENERATOR_STACK_PAGE_SLOTS (256)
135
136#define ZEND_VM_STACK_PAGE_SLOTS(gen) ((gen) ? ZEND_VM_GENERATOR_STACK_PAGE_SLOTS : ZEND_VM_MAIN_STACK_PAGE_SLOTS)
137
138#define ZEND_VM_STACK_PAGE_SIZE(gen)  (ZEND_VM_STACK_PAGE_SLOTS(gen) * sizeof(zval))
139
140#define ZEND_VM_STACK_FREE_PAGE_SIZE(gen) \
141    ((ZEND_VM_STACK_PAGE_SLOTS(gen) - ZEND_VM_STACK_HEADER_SLOTS) * sizeof(zval))
142
143#define ZEND_VM_STACK_PAGE_ALIGNED_SIZE(gen, size) \
144    (((size) + (ZEND_VM_STACK_FREE_PAGE_SIZE(gen) - 1)) & ~(ZEND_VM_STACK_PAGE_SIZE(gen) - 1))
145
146static zend_always_inline zend_vm_stack zend_vm_stack_new_page(size_t size, zend_vm_stack prev) {
147    zend_vm_stack page = (zend_vm_stack)emalloc(size);
148
149    page->top = ZEND_VM_STACK_ELEMETS(page);
150    page->end = (zval*)((char*)page + size);
151    page->prev = prev;
152    return page;
153}
154
155ZEND_API void zend_vm_stack_init(void)
156{
157    EG(vm_stack) = zend_vm_stack_new_page(ZEND_VM_STACK_PAGE_SIZE(0 /* main stack */), NULL);
158    EG(vm_stack)->top++;
159    EG(vm_stack_top) = EG(vm_stack)->top;
160    EG(vm_stack_end) = EG(vm_stack)->end;
161}
162
163ZEND_API void zend_vm_stack_destroy(void)
164{
165    zend_vm_stack stack = EG(vm_stack);
166
167    while (stack != NULL) {
168        zend_vm_stack p = stack->prev;
169        efree(stack);
170        stack = p;
171    }
172}
173
174ZEND_API void* zend_vm_stack_extend(size_t size)
175{
176    zend_vm_stack stack;
177    void *ptr;
178
179    stack = EG(vm_stack);
180    stack->top = EG(vm_stack_top);
181    EG(vm_stack) = stack = zend_vm_stack_new_page(
182        EXPECTED(size < ZEND_VM_STACK_FREE_PAGE_SIZE(0)) ?
183            ZEND_VM_STACK_PAGE_SIZE(0) : ZEND_VM_STACK_PAGE_ALIGNED_SIZE(0, size),
184        stack);
185    ptr = stack->top;
186    EG(vm_stack_top) = (void*)(((char*)ptr) + size);
187    EG(vm_stack_end) = stack->end;
188    return ptr;
189}
190
191ZEND_API zval* zend_get_compiled_variable_value(const zend_execute_data *execute_data, uint32_t var)
192{
193    return EX_VAR(var);
194}
195
196static zend_always_inline zval *_get_zval_ptr_tmp(uint32_t var, const zend_execute_data *execute_data, zend_free_op *should_free)
197{
198    zval *ret = EX_VAR(var);
199    *should_free = ret;
200
201    ZEND_ASSERT(Z_TYPE_P(ret) != IS_REFERENCE);
202
203    return ret;
204}
205
206static zend_always_inline zval *_get_zval_ptr_var(uint32_t var, const zend_execute_data *execute_data, zend_free_op *should_free)
207{
208    zval *ret = EX_VAR(var);
209
210    *should_free = ret;
211    return ret;
212}
213
214static zend_always_inline zval *_get_zval_ptr_var_deref(uint32_t var, const zend_execute_data *execute_data, zend_free_op *should_free)
215{
216    zval *ret = EX_VAR(var);
217
218    *should_free = ret;
219    ZVAL_DEREF(ret);
220    return ret;
221}
222
223static zend_never_inline zval *_get_zval_cv_lookup(zval *ptr, uint32_t var, int type, const zend_execute_data *execute_data)
224{
225    zend_string *cv;
226
227    switch (type) {
228        case BP_VAR_R:
229        case BP_VAR_UNSET:
230            cv = CV_DEF_OF(EX_VAR_TO_NUM(var));
231            zend_error(E_NOTICE, "Undefined variable: %s", ZSTR_VAL(cv));
232            /* break missing intentionally */
233        case BP_VAR_IS:
234            ptr = &EG(uninitialized_zval);
235            break;
236        case BP_VAR_RW:
237            cv = CV_DEF_OF(EX_VAR_TO_NUM(var));
238            zend_error(E_NOTICE, "Undefined variable: %s", ZSTR_VAL(cv));
239            /* break missing intentionally */
240        case BP_VAR_W:
241            ZVAL_NULL(ptr);
242            break;
243    }
244    return ptr;
245}
246
247static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_R(zval *ptr, uint32_t var, const zend_execute_data *execute_data)
248{
249    zend_string *cv = CV_DEF_OF(EX_VAR_TO_NUM(var));
250
251    zend_error(E_NOTICE, "Undefined variable: %s", ZSTR_VAL(cv));
252    return &EG(uninitialized_zval);
253}
254
255static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_UNSET(zval *ptr, uint32_t var, const zend_execute_data *execute_data)
256{
257    zend_string *cv = CV_DEF_OF(EX_VAR_TO_NUM(var));
258
259    zend_error(E_NOTICE, "Undefined variable: %s", ZSTR_VAL(cv));
260    return &EG(uninitialized_zval);
261}
262
263static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_RW(zval *ptr, uint32_t var, const zend_execute_data *execute_data)
264{
265    zend_string *cv = CV_DEF_OF(EX_VAR_TO_NUM(var));
266
267    ZVAL_NULL(ptr);
268    zend_error(E_NOTICE, "Undefined variable: %s", ZSTR_VAL(cv));
269    return ptr;
270}
271
272static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_W(zval *ptr, uint32_t var, const zend_execute_data *execute_data)
273{
274    ZVAL_NULL(ptr);
275    return ptr;
276}
277
278static zend_always_inline zval *_get_zval_ptr_cv(const zend_execute_data *execute_data, uint32_t var, int type)
279{
280    zval *ret = EX_VAR(var);
281
282    if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
283        return _get_zval_cv_lookup(ret, var, type, execute_data);
284    }
285    return ret;
286}
287
288static zend_always_inline zval *_get_zval_ptr_cv_undef(const zend_execute_data *execute_data, uint32_t var)
289{
290    return EX_VAR(var);
291}
292
293static zend_always_inline zval *_get_zval_ptr_cv_deref(const zend_execute_data *execute_data, uint32_t var, int type)
294{
295    zval *ret = EX_VAR(var);
296
297    if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
298        return _get_zval_cv_lookup(ret, var, type, execute_data);
299    }
300    ZVAL_DEREF(ret);
301    return ret;
302}
303
304static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_R(const zend_execute_data *execute_data, uint32_t var)
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_R(ret, var, execute_data);
310    }
311    return ret;
312}
313
314static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_R(const zend_execute_data *execute_data, uint32_t var)
315{
316    zval *ret = EX_VAR(var);
317
318    if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
319        return _get_zval_cv_lookup_BP_VAR_R(ret, var, execute_data);
320    }
321    ZVAL_DEREF(ret);
322    return ret;
323}
324
325static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_UNSET(const zend_execute_data *execute_data, uint32_t var)
326{
327    zval *ret = EX_VAR(var);
328
329    if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
330        return _get_zval_cv_lookup_BP_VAR_UNSET(ret, var, execute_data);
331    }
332    return ret;
333}
334
335static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_UNSET(const zend_execute_data *execute_data, uint32_t var)
336{
337    zval *ret = EX_VAR(var);
338
339    if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
340        return _get_zval_cv_lookup_BP_VAR_UNSET(ret, var, execute_data);
341    }
342    ZVAL_DEREF(ret);
343    return ret;
344}
345
346static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_IS(const zend_execute_data *execute_data, uint32_t var)
347{
348    zval *ret = EX_VAR(var);
349
350    return ret;
351}
352
353static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_IS(const zend_execute_data *execute_data, uint32_t var)
354{
355    zval *ret = EX_VAR(var);
356
357    ZVAL_DEREF(ret);
358    return ret;
359}
360
361static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_RW(const zend_execute_data *execute_data, uint32_t var)
362{
363    zval *ret = EX_VAR(var);
364
365    if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
366        return _get_zval_cv_lookup_BP_VAR_RW(ret, var, execute_data);
367    }
368    return ret;
369}
370
371static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_RW(const zend_execute_data *execute_data, uint32_t var)
372{
373    zval *ret = EX_VAR(var);
374
375    if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
376        return _get_zval_cv_lookup_BP_VAR_RW(ret, var, execute_data);
377    }
378    ZVAL_DEREF(ret);
379    return ret;
380}
381
382static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_W(const zend_execute_data *execute_data, uint32_t var)
383{
384    zval *ret = EX_VAR(var);
385
386    if (Z_TYPE_P(ret) == IS_UNDEF) {
387        return _get_zval_cv_lookup_BP_VAR_W(ret, var, execute_data);
388    }
389    return ret;
390}
391
392static zend_always_inline zval *_get_zval_ptr_cv_undef_BP_VAR_W(const zend_execute_data *execute_data, uint32_t var)
393{
394    return EX_VAR(var);
395}
396
397static zend_always_inline zval *_get_zval_ptr_cv_undef_BP_VAR_RW(const zend_execute_data *execute_data, uint32_t var)
398{
399    return EX_VAR(var);
400}
401
402static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_W(const zend_execute_data *execute_data, uint32_t var)
403{
404    zval *ret = EX_VAR(var);
405
406    if (Z_TYPE_P(ret) == IS_UNDEF) {
407        return _get_zval_cv_lookup_BP_VAR_W(ret, var, execute_data);
408    }
409    ZVAL_DEREF(ret);
410    return ret;
411}
412
413static zend_always_inline zval *_get_zval_ptr(int op_type, znode_op node, const zend_execute_data *execute_data, zend_free_op *should_free, int type)
414{
415    if (op_type & (IS_TMP_VAR|IS_VAR)) {
416        if (op_type == IS_TMP_VAR) {
417            return _get_zval_ptr_tmp(node.var, execute_data, should_free);
418        } else {
419            ZEND_ASSERT(op_type == IS_VAR);
420            return _get_zval_ptr_var(node.var, execute_data, should_free);
421        }
422    } else {
423        *should_free = NULL;
424        if (op_type == IS_CONST) {
425            return EX_CONSTANT(node);
426        } else if (op_type == IS_CV) {
427            return _get_zval_ptr_cv(execute_data, node.var, type);
428        } else {
429            return NULL;
430        }
431    }
432}
433
434static zend_always_inline zval *_get_zval_ptr_deref(int op_type, znode_op node, const zend_execute_data *execute_data, zend_free_op *should_free, int type)
435{
436    if (op_type & (IS_TMP_VAR|IS_VAR)) {
437        if (op_type == IS_TMP_VAR) {
438            return _get_zval_ptr_tmp(node.var, execute_data, should_free);
439        } else {
440            ZEND_ASSERT(op_type == IS_VAR);
441            return _get_zval_ptr_var_deref(node.var, execute_data, should_free);
442        }
443    } else {
444        *should_free = NULL;
445        if (op_type == IS_CONST) {
446            return EX_CONSTANT(node);
447        } else if (op_type == IS_CV) {
448            return _get_zval_ptr_cv_deref(execute_data, node.var, type);
449        } else {
450            return NULL;
451        }
452    }
453}
454
455static zend_always_inline zval *_get_zval_ptr_undef(int op_type, znode_op node, const zend_execute_data *execute_data, zend_free_op *should_free, int type)
456{
457    if (op_type & (IS_TMP_VAR|IS_VAR)) {
458        if (op_type == IS_TMP_VAR) {
459            return _get_zval_ptr_tmp(node.var, execute_data, should_free);
460        } else {
461            ZEND_ASSERT(op_type == IS_VAR);
462            return _get_zval_ptr_var(node.var, execute_data, should_free);
463        }
464    } else {
465        *should_free = NULL;
466        if (op_type == IS_CONST) {
467            return EX_CONSTANT(node);
468        } else if (op_type == IS_CV) {
469            return _get_zval_ptr_cv_undef(execute_data, node.var);
470        } else {
471            return NULL;
472        }
473    }
474}
475
476static zend_always_inline zval *_get_zval_ptr_ptr_var(uint32_t var, const zend_execute_data *execute_data, zend_free_op *should_free)
477{
478    zval *ret = EX_VAR(var);
479
480    if (EXPECTED(Z_TYPE_P(ret) == IS_INDIRECT)) {
481        *should_free = NULL;
482        ret = Z_INDIRECT_P(ret);
483    } else if (!Z_REFCOUNTED_P(ret)) {
484        *should_free = ret; /* immutable array may be converted to regular */
485    } else if (Z_REFCOUNT_P(ret) == 1) {
486        *should_free = ret;
487    } else {
488        *should_free = NULL;
489        Z_DELREF_P(ret);
490    }
491    return ret;
492}
493
494static inline zval *_get_zval_ptr_ptr(int op_type, znode_op node, const zend_execute_data *execute_data, zend_free_op *should_free, int type)
495{
496    if (op_type == IS_CV) {
497        *should_free = NULL;
498        return _get_zval_ptr_cv(execute_data, node.var, type);
499    } else /* if (op_type == IS_VAR) */ {
500        ZEND_ASSERT(op_type == IS_VAR);
501        return _get_zval_ptr_ptr_var(node.var, execute_data, should_free);
502    }
503}
504
505static zend_always_inline zval *_get_obj_zval_ptr_unused(zend_execute_data *execute_data)
506{
507    return &EX(This);
508}
509
510static inline zval *_get_obj_zval_ptr(int op_type, znode_op op, zend_execute_data *execute_data, zend_free_op *should_free, int type)
511{
512    if (op_type == IS_UNUSED) {
513        *should_free = NULL;
514        return &EX(This);
515    }
516    return get_zval_ptr(op_type, op, execute_data, should_free, type);
517}
518
519static inline zval *_get_obj_zval_ptr_undef(int op_type, znode_op op, zend_execute_data *execute_data, zend_free_op *should_free, int type)
520{
521    if (op_type == IS_UNUSED) {
522        *should_free = NULL;
523        return &EX(This);
524    }
525    return get_zval_ptr_undef(op_type, op, execute_data, should_free, type);
526}
527
528static inline zval *_get_obj_zval_ptr_ptr(int op_type, znode_op node, zend_execute_data *execute_data, zend_free_op *should_free, int type)
529{
530    if (op_type == IS_UNUSED) {
531        *should_free = NULL;
532        return &EX(This);
533    }
534    return get_zval_ptr_ptr(op_type, node, execute_data, should_free, type);
535}
536
537static inline void zend_assign_to_variable_reference(zval *variable_ptr, zval *value_ptr)
538{
539    zend_reference *ref;
540
541    if (EXPECTED(!Z_ISREF_P(value_ptr))) {
542        ZVAL_NEW_REF(value_ptr, value_ptr);
543    } else if (UNEXPECTED(variable_ptr == value_ptr)) {
544        return;
545    }
546
547    ref = Z_REF_P(value_ptr);
548    GC_REFCOUNT(ref)++;
549    zval_ptr_dtor(variable_ptr);
550    ZVAL_REF(variable_ptr, ref);
551}
552
553/* this should modify object only if it's empty */
554static inline int make_real_object(zval *object)
555{
556    if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
557        if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE)) {
558            /* nothing to destroy */
559        } else if (EXPECTED((Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) {
560            zval_ptr_dtor_nogc(object);
561        } else {
562            return 0;
563        }
564        object_init(object);
565        zend_error(E_WARNING, "Creating default object from empty value");
566    }
567    return 1;
568}
569
570ZEND_API char * zend_verify_internal_arg_class_kind(const zend_internal_arg_info *cur_arg_info, char **class_name, zend_class_entry **pce)
571{
572    zend_string *key;
573    ALLOCA_FLAG(use_heap);
574
575    ZSTR_ALLOCA_INIT(key, cur_arg_info->class_name, strlen(cur_arg_info->class_name), use_heap);
576    *pce = zend_fetch_class(key, (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD));
577    ZSTR_ALLOCA_FREE(key, use_heap);
578
579    *class_name = (*pce) ? ZSTR_VAL((*pce)->name) : (char*)cur_arg_info->class_name;
580    if (*pce && (*pce)->ce_flags & ZEND_ACC_INTERFACE) {
581        return "implement interface ";
582    } else {
583        return "be an instance of ";
584    }
585}
586
587static zend_always_inline zend_class_entry* zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info)
588{
589    return zend_fetch_class(cur_arg_info->class_name, (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD));
590}
591
592ZEND_API void zend_verify_arg_error(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)
593{
594    zend_execute_data *ptr = EG(current_execute_data)->prev_execute_data;
595    const char *fname = ZSTR_VAL(zf->common.function_name);
596    const char *fsep;
597    const char *fclass;
598
599    if (zf->common.scope) {
600        fsep =  "::";
601        fclass = ZSTR_VAL(zf->common.scope->name);
602    } else {
603        fsep =  "";
604        fclass = "";
605    }
606
607    if (zf->common.type == ZEND_USER_FUNCTION) {
608        if (ptr && ptr->func && ZEND_USER_CODE(ptr->func->common.type)) {
609            zend_type_error("Argument %d passed to %s%s%s() must %s%s, %s%s given, called in %s on line %d",
610                    arg_num, fclass, fsep, fname, need_msg, need_kind, given_msg, given_kind,
611                    ZSTR_VAL(ptr->func->op_array.filename), ptr->opline->lineno);
612        } else {
613            zend_type_error("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);
614        }
615    } else {
616        zend_type_error("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);
617    }
618}
619
620static int is_null_constant(zval *default_value)
621{
622    if (Z_CONSTANT_P(default_value)) {
623        zval constant;
624
625        ZVAL_COPY_VALUE(&constant, default_value);
626        if (UNEXPECTED(zval_update_constant_ex(&constant, 0, NULL) != SUCCESS)) {
627            return 0;
628        }
629        if (Z_TYPE(constant) == IS_NULL) {
630            return 1;
631        }
632        zval_dtor(&constant);
633    }
634    return 0;
635}
636
637static zend_bool zend_verify_weak_scalar_type_hint(zend_uchar type_hint, zval *arg)
638{
639    switch (type_hint) {
640        case _IS_BOOL: {
641            zend_bool dest;
642
643            if (!zend_parse_arg_bool_weak(arg, &dest)) {
644                return 0;
645            }
646            zval_ptr_dtor(arg);
647            ZVAL_BOOL(arg, dest);
648            return 1;
649        }
650        case IS_LONG: {
651            zend_long dest;
652
653            if (!zend_parse_arg_long_weak(arg, &dest)) {
654                return 0;
655            }
656            zval_ptr_dtor(arg);
657            ZVAL_LONG(arg, dest);
658            return 1;
659        }
660        case IS_DOUBLE: {
661            double dest;
662
663            if (!zend_parse_arg_double_weak(arg, &dest)) {
664                return 0;
665            }
666            zval_ptr_dtor(arg);
667            ZVAL_DOUBLE(arg, dest);
668            return 1;
669        }
670        case IS_STRING: {
671            zend_string *dest;
672
673            /* on success "arg" is converted to IS_STRING */
674            if (!zend_parse_arg_str_weak(arg, &dest)) {
675                return 0;
676            }
677            return 1;
678        }
679        default:
680            return 0;
681    }
682}
683
684static zend_bool zend_verify_scalar_type_hint(zend_uchar type_hint, zval *arg, zend_bool strict)
685{
686    if (UNEXPECTED(strict)) {
687        /* SSTH Exception: IS_LONG may be accepted as IS_DOUBLE (converted) */
688        if (type_hint != IS_DOUBLE || Z_TYPE_P(arg) != IS_LONG) {
689            return 0;
690        }
691    } else if (UNEXPECTED(Z_TYPE_P(arg) == IS_NULL)) {
692        /* NULL may be accepted only by nullable hints (this is already checked) */
693        return 0;
694    }
695    return zend_verify_weak_scalar_type_hint(type_hint, arg);
696}
697
698static void zend_verify_internal_arg_type(zend_function *zf, uint32_t arg_num, zval *arg)
699{
700    zend_internal_arg_info *cur_arg_info;
701    char *need_msg, *class_name;
702    zend_class_entry *ce;
703
704    if (EXPECTED(arg_num <= zf->internal_function.num_args)) {
705        cur_arg_info = &zf->internal_function.arg_info[arg_num-1];
706    } else if (zf->internal_function.fn_flags & ZEND_ACC_VARIADIC) {
707        cur_arg_info = &zf->internal_function.arg_info[zf->internal_function.num_args];
708    } else {
709        return;
710    }
711
712    if (cur_arg_info->type_hint) {
713        ZVAL_DEREF(arg);
714        if (EXPECTED(cur_arg_info->type_hint == Z_TYPE_P(arg))) {
715            if (cur_arg_info->class_name) {
716                need_msg = zend_verify_internal_arg_class_kind((zend_internal_arg_info*)cur_arg_info, &class_name, &ce);
717                if (!ce || !instanceof_function(Z_OBJCE_P(arg), ce)) {
718                    zend_verify_arg_error(zf, arg_num, need_msg, class_name, "instance of ", ZSTR_VAL(Z_OBJCE_P(arg)->name), arg);
719                }
720            }
721        } else if (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null) {
722            if (cur_arg_info->class_name) {
723                need_msg = zend_verify_internal_arg_class_kind((zend_internal_arg_info*)cur_arg_info, &class_name, &ce);
724                zend_verify_arg_error(zf, arg_num, need_msg, class_name, zend_zval_type_name(arg), "", arg);
725            } else if (cur_arg_info->type_hint == IS_CALLABLE) {
726                if (!zend_is_callable(arg, IS_CALLABLE_CHECK_SILENT, NULL)) {
727                    zend_verify_arg_error(zf, arg_num, "be callable", "", zend_zval_type_name(arg), "", arg);
728                }
729            } else if (cur_arg_info->type_hint == _IS_BOOL &&
730                       EXPECTED(Z_TYPE_P(arg) == IS_FALSE || Z_TYPE_P(arg) == IS_TRUE)) {
731                /* pass */
732            } else if (UNEXPECTED(!zend_verify_scalar_type_hint(cur_arg_info->type_hint, arg, ZEND_CALL_USES_STRICT_TYPES(EG(current_execute_data))))) {
733                zend_verify_arg_error(zf, arg_num, "be of the type ", zend_get_type_by_const(cur_arg_info->type_hint), zend_zval_type_name(arg), "", arg);
734            }
735        }
736    }
737}
738
739static zend_always_inline int zend_verify_arg_type(zend_function *zf, uint32_t arg_num, zval *arg, zval *default_value, void **cache_slot)
740{
741    zend_arg_info *cur_arg_info;
742    char *need_msg;
743    zend_class_entry *ce;
744
745    if (EXPECTED(arg_num <= zf->common.num_args)) {
746        cur_arg_info = &zf->common.arg_info[arg_num-1];
747    } else if (UNEXPECTED(zf->common.fn_flags & ZEND_ACC_VARIADIC)) {
748        cur_arg_info = &zf->common.arg_info[zf->common.num_args];
749    } else {
750        return 1;
751    }
752
753    if (cur_arg_info->type_hint) {
754        ZVAL_DEREF(arg);
755        if (EXPECTED(cur_arg_info->type_hint == Z_TYPE_P(arg))) {
756            if (cur_arg_info->class_name) {
757                if (EXPECTED(*cache_slot)) {
758                    ce = (zend_class_entry*)*cache_slot;
759                } else {
760                    ce = zend_verify_arg_class_kind(cur_arg_info);
761                    if (UNEXPECTED(!ce)) {
762                        zend_verify_arg_error(zf, arg_num, "be an instance of ", ZSTR_VAL(cur_arg_info->class_name), "instance of ", ZSTR_VAL(Z_OBJCE_P(arg)->name), arg);
763                        return 0;
764                    }
765                    *cache_slot = (void*)ce;
766                }
767                if (UNEXPECTED(!instanceof_function(Z_OBJCE_P(arg), ce))) {
768                    need_msg =
769                        (ce->ce_flags & ZEND_ACC_INTERFACE) ?
770                        "implement interface " : "be an instance of ";
771                    zend_verify_arg_error(zf, arg_num, need_msg, ZSTR_VAL(ce->name), "instance of ", ZSTR_VAL(Z_OBJCE_P(arg)->name), arg);
772                    return 0;
773                }
774            }
775        } else if (Z_TYPE_P(arg) != IS_NULL || !(cur_arg_info->allow_null || (default_value && is_null_constant(default_value)))) {
776            if (cur_arg_info->class_name) {
777                if (EXPECTED(*cache_slot)) {
778                    ce = (zend_class_entry*)*cache_slot;
779                } else {
780                    ce = zend_verify_arg_class_kind(cur_arg_info);
781                    if (UNEXPECTED(!ce)) {
782                        if (Z_TYPE_P(arg) == IS_OBJECT) {
783                            zend_verify_arg_error(zf, arg_num, "be an instance of ", ZSTR_VAL(cur_arg_info->class_name), "instance of ", ZSTR_VAL(Z_OBJCE_P(arg)->name), arg);
784                        } else {
785                            zend_verify_arg_error(zf, arg_num, "be an instance of ", ZSTR_VAL(cur_arg_info->class_name), "", zend_zval_type_name(arg), arg);
786                        }
787                        return 0;
788                    }
789                    *cache_slot = (void*)ce;
790                }
791                need_msg =
792                    (ce->ce_flags & ZEND_ACC_INTERFACE) ?
793                    "implement interface " : "be an instance of ";
794                zend_verify_arg_error(zf, arg_num, need_msg, ZSTR_VAL(ce->name), zend_zval_type_name(arg), "", arg);
795                return 0;
796            } else if (cur_arg_info->type_hint == IS_CALLABLE) {
797                if (!zend_is_callable(arg, IS_CALLABLE_CHECK_SILENT, NULL)) {
798                    zend_verify_arg_error(zf, arg_num, "be callable", "", zend_zval_type_name(arg), "", arg);
799                    return 0;
800                }
801            } else if (cur_arg_info->type_hint == _IS_BOOL &&
802                       EXPECTED(Z_TYPE_P(arg) == IS_FALSE || Z_TYPE_P(arg) == IS_TRUE)) {
803                /* pass */
804            } else if (UNEXPECTED(!zend_verify_scalar_type_hint(cur_arg_info->type_hint, arg, ZEND_ARG_USES_STRICT_TYPES()))) {
805                zend_verify_arg_error(zf, arg_num, "be of the type ", zend_get_type_by_const(cur_arg_info->type_hint), zend_zval_type_name(arg), "", arg);
806                return 0;
807            }
808        }
809    }
810    return 1;
811}
812
813static zend_always_inline int zend_verify_missing_arg_type(zend_function *zf, uint32_t arg_num, void **cache_slot)
814{
815    zend_arg_info *cur_arg_info;
816    char *need_msg;
817    zend_class_entry *ce;
818
819    if (EXPECTED(arg_num <= zf->common.num_args)) {
820        cur_arg_info = &zf->common.arg_info[arg_num-1];
821    } else if (UNEXPECTED(zf->common.fn_flags & ZEND_ACC_VARIADIC)) {
822        cur_arg_info = &zf->common.arg_info[zf->common.num_args];
823    } else {
824        return 1;
825    }
826
827    if (cur_arg_info->type_hint) {
828        if (cur_arg_info->class_name) {
829            if (EXPECTED(*cache_slot)) {
830                ce = (zend_class_entry*)*cache_slot;
831            } else {
832                ce = zend_verify_arg_class_kind(cur_arg_info);
833                if (UNEXPECTED(!ce)) {
834                    zend_verify_arg_error(zf, arg_num, "be an instance of ", ZSTR_VAL(cur_arg_info->class_name), "none", "", NULL);
835                    return 0;
836                }
837                *cache_slot = (void*)ce;
838            }
839            need_msg =
840                (ce->ce_flags & ZEND_ACC_INTERFACE) ?
841                "implement interface " : "be an instance of ";
842            zend_verify_arg_error(zf, arg_num, need_msg, ZSTR_VAL(ce->name), "none", "", NULL);
843        } else if (cur_arg_info->type_hint == IS_CALLABLE) {
844            zend_verify_arg_error(zf, arg_num, "be callable", "", "none", "", NULL);
845        } else {
846            zend_verify_arg_error(zf, arg_num, "be of the type ", zend_get_type_by_const(cur_arg_info->type_hint), "none", "", NULL);
847        }
848        return 0;
849    }
850    return 1;
851}
852
853static zend_always_inline int zend_verify_missing_arg(zend_execute_data *execute_data, uint32_t arg_num, void **cache_slot)
854{
855    if (EXPECTED(!(EX(func)->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS)) ||
856        zend_verify_missing_arg_type(EX(func), arg_num, cache_slot)) {
857        const char *class_name = EX(func)->common.scope ? ZSTR_VAL(EX(func)->common.scope->name) : "";
858        const char *space = EX(func)->common.scope ? "::" : "";
859        const char *func_name = EX(func)->common.function_name ? ZSTR_VAL(EX(func)->common.function_name) : "main";
860        zend_execute_data *ptr = EX(prev_execute_data);
861
862        if (ptr && ptr->func && ZEND_USER_CODE(ptr->func->common.type)) {
863            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, ZSTR_VAL(ptr->func->op_array.filename), ptr->opline->lineno);
864        } else {
865            zend_error(E_WARNING, "Missing argument %u for %s%s%s()", arg_num, class_name, space, func_name);
866        }
867        return 1;
868    }
869    return 0;
870}
871
872ZEND_API void zend_verify_return_error(const zend_function *zf, const char *need_msg, const char *need_kind, const char *returned_msg, const char *returned_kind)
873{
874    const char *fname = ZSTR_VAL(zf->common.function_name);
875    const char *fsep;
876    const char *fclass;
877
878    if (zf->common.scope) {
879        fsep =  "::";
880        fclass = ZSTR_VAL(zf->common.scope->name);
881    } else {
882        fsep =  "";
883        fclass = "";
884    }
885
886    if (zf->common.type == ZEND_USER_FUNCTION) {
887        zend_type_error("Return value of %s%s%s() must %s%s, %s%s returned in %s on line %d",
888            fclass, fsep, fname, need_msg, need_kind, returned_msg, returned_kind,
889            ZSTR_VAL(zf->op_array.filename), EG(current_execute_data)->opline->lineno);
890    } else {
891        zend_type_error("Return value of %s%s%s() must %s%s, %s%s returned",
892            fclass, fsep, fname, need_msg, need_kind, returned_msg, returned_kind);
893    }
894}
895
896ZEND_API void zend_verify_internal_return_error(const zend_function *zf, const char *need_msg, const char *need_kind, const char *returned_msg, const char *returned_kind)
897{
898    const char *fname = ZSTR_VAL(zf->common.function_name);
899    const char *fsep;
900    const char *fclass;
901
902    if (zf->common.scope) {
903        fsep =  "::";
904        fclass = ZSTR_VAL(zf->common.scope->name);
905    } else {
906        fsep =  "";
907        fclass = "";
908    }
909
910    zend_error_noreturn(E_CORE_ERROR, "Return value of %s%s%s() must %s%s, %s%s returned",
911        fclass, fsep, fname, need_msg, need_kind, returned_msg, returned_kind);
912}
913
914#if ZEND_DEBUG
915static int zend_verify_internal_return_type(zend_function *zf, zval *ret)
916{
917    zend_arg_info *ret_info = zf->common.arg_info - 1;
918    char *need_msg, *class_name;
919    zend_class_entry *ce;
920
921
922    if (ret_info->type_hint) {
923        if (EXPECTED(ret_info->type_hint == Z_TYPE_P(ret))) {
924            if (ret_info->class_name) {
925                need_msg = zend_verify_internal_arg_class_kind((zend_internal_arg_info *)ret_info, &class_name, &ce);
926                if (!ce || !instanceof_function(Z_OBJCE_P(ret), ce)) {
927                    zend_verify_internal_return_error(zf, need_msg, class_name, "instance of ", ZSTR_VAL(Z_OBJCE_P(ret)->name));
928                    return 0;
929                }
930            }
931        } else if (Z_TYPE_P(ret) != IS_NULL || !ret_info->allow_null) {
932            if (ret_info->class_name) {
933                need_msg = zend_verify_internal_arg_class_kind((zend_internal_arg_info *)ret_info, &class_name, &ce);
934                zend_verify_internal_return_error(zf, need_msg, class_name, zend_zval_type_name(ret), "");
935            } else if (ret_info->type_hint == IS_CALLABLE) {
936                if (!zend_is_callable(ret, IS_CALLABLE_CHECK_SILENT, NULL) && (Z_TYPE_P(ret) != IS_NULL || !ret_info->allow_null)) {
937                    zend_verify_internal_return_error(zf, "be callable", "", zend_zval_type_name(ret), "");
938                    return 0;
939                }
940            } else if (ret_info->type_hint == _IS_BOOL &&
941                       EXPECTED(Z_TYPE_P(ret) == IS_FALSE || Z_TYPE_P(ret) == IS_TRUE)) {
942                /* pass */
943            } else {
944                /* Use strict check to verify return value of internal function */
945                zend_verify_internal_return_error(zf, "be of the type ", zend_get_type_by_const(ret_info->type_hint), zend_zval_type_name(ret), "");
946                return 0;
947            }
948        }
949    }
950    return 1;
951}
952#endif
953
954static zend_always_inline void zend_verify_return_type(zend_function *zf, zval *ret, void **cache_slot)
955{
956    zend_arg_info *ret_info = zf->common.arg_info - 1;
957    char *need_msg;
958    zend_class_entry *ce;
959
960    if (ret_info->type_hint) {
961        if (EXPECTED(ret_info->type_hint == Z_TYPE_P(ret))) {
962            if (ret_info->class_name) {
963                if (EXPECTED(*cache_slot)) {
964                    ce = (zend_class_entry*)*cache_slot;
965                } else {
966                    ce = zend_verify_arg_class_kind(ret_info);
967                    if (UNEXPECTED(!ce)) {
968                        zend_verify_return_error(zf, "be an instance of ", ZSTR_VAL(ret_info->class_name), "instance of ", ZSTR_VAL(Z_OBJCE_P(ret)->name));
969                        return;
970                    }
971                    *cache_slot = (void*)ce;
972                }
973                if (UNEXPECTED(!instanceof_function(Z_OBJCE_P(ret), ce))) {
974                    need_msg =
975                        (ce->ce_flags & ZEND_ACC_INTERFACE) ?
976                        "implement interface " : "be an instance of ";
977                    zend_verify_return_error(zf, need_msg, ZSTR_VAL(ce->name), "instance of ", ZSTR_VAL(Z_OBJCE_P(ret)->name));
978                }
979            }
980        } else if (Z_TYPE_P(ret) != IS_NULL || !ret_info->allow_null) {
981            if (ret_info->class_name) {
982                if (EXPECTED(*cache_slot)) {
983                    ce = (zend_class_entry*)*cache_slot;
984                } else {
985                    ce = zend_verify_arg_class_kind(ret_info);
986                    if (UNEXPECTED(!ce)) {
987                        zend_verify_return_error(zf, "be an instance of ", ZSTR_VAL(ret_info->class_name), zend_zval_type_name(ret), "");
988                        return;
989                    }
990                    *cache_slot = (void*)ce;
991                }
992                need_msg =
993                    (ce->ce_flags & ZEND_ACC_INTERFACE) ?
994                    "implement interface " : "be an instance of ";
995                zend_verify_return_error(zf, need_msg, ZSTR_VAL(ce->name), zend_zval_type_name(ret), "");
996            } else if (ret_info->type_hint == IS_CALLABLE) {
997                if (!zend_is_callable(ret, IS_CALLABLE_CHECK_SILENT, NULL)) {
998                    zend_verify_return_error(zf, "be callable", "", zend_zval_type_name(ret), "");
999                }
1000            } else if (ret_info->type_hint == _IS_BOOL &&
1001                       EXPECTED(Z_TYPE_P(ret) == IS_FALSE || Z_TYPE_P(ret) == IS_TRUE)) {
1002                /* pass */
1003            } else if (UNEXPECTED(!zend_verify_scalar_type_hint(ret_info->type_hint, ret, ZEND_RET_USES_STRICT_TYPES()))) {
1004                zend_verify_return_error(zf, "be of the type ", zend_get_type_by_const(ret_info->type_hint), zend_zval_type_name(ret), "");
1005            }
1006        }
1007    }
1008}
1009
1010static zend_always_inline int zend_verify_missing_return_type(zend_function *zf, void **cache_slot)
1011{
1012    zend_arg_info *ret_info = zf->common.arg_info - 1;
1013    char *need_msg;
1014    zend_class_entry *ce;
1015
1016    if (ret_info->type_hint) {
1017        if (ret_info->class_name) {
1018            if (EXPECTED(*cache_slot)) {
1019                ce = (zend_class_entry*)*cache_slot;
1020            } else {
1021                ce = zend_verify_arg_class_kind(ret_info);
1022                if (UNEXPECTED(!ce)) {
1023                    zend_verify_return_error(zf, "be an instance of ", ZSTR_VAL(ret_info->class_name), "none", "");
1024                    return 0;
1025                }
1026                *cache_slot = (void*)ce;
1027            }
1028            need_msg =
1029                (ce->ce_flags & ZEND_ACC_INTERFACE) ?
1030                "implement interface " : "be an instance of ";
1031            zend_verify_return_error(zf, need_msg, ZSTR_VAL(ce->name), "none", "");
1032            return 0;
1033        } else if (ret_info->type_hint == IS_CALLABLE) {
1034            zend_verify_return_error(zf, "be callable", "", "none", "");
1035        } else {
1036            zend_verify_return_error(zf, "be of the type ", zend_get_type_by_const(ret_info->type_hint), "none", "");
1037        }
1038        return 0;
1039    }
1040    return 1;
1041}
1042
1043static zend_always_inline void zend_assign_to_object(zval *retval, zval *object, uint32_t object_op_type, zval *property_name, uint32_t property_op_type, int value_type, znode_op value_op, const zend_execute_data *execute_data, void **cache_slot)
1044{
1045    zend_free_op free_value;
1046    zval *value = get_zval_ptr(value_type, value_op, execute_data, &free_value, BP_VAR_R);
1047    zval tmp;
1048
1049    if (object_op_type != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
1050        do {
1051            if (object_op_type == IS_VAR && UNEXPECTED(object == &EG(error_zval))) {
1052                if (retval) {
1053                    ZVAL_NULL(retval);
1054                }
1055                FREE_OP(free_value);
1056                return;
1057            }
1058            if (Z_ISREF_P(object)) {
1059                object = Z_REFVAL_P(object);
1060                if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
1061                    break;
1062                }
1063            }
1064            if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE ||
1065                (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) {
1066                zend_object *obj;
1067
1068                zval_ptr_dtor(object);
1069                object_init(object);
1070                Z_ADDREF_P(object);
1071                obj = Z_OBJ_P(object);
1072                zend_error(E_WARNING, "Creating default object from empty value");
1073                if (GC_REFCOUNT(obj) == 1) {
1074                    /* the enclosing container was deleted, obj is unreferenced */
1075                    if (retval) {
1076                        ZVAL_NULL(retval);
1077                    }
1078                    FREE_OP(free_value);
1079                    OBJ_RELEASE(obj);
1080                    return;
1081                }
1082                Z_DELREF_P(object);
1083            } else {
1084                zend_error(E_WARNING, "Attempt to assign property of non-object");
1085                if (retval) {
1086                    ZVAL_NULL(retval);
1087                }
1088                FREE_OP(free_value);
1089                return;
1090            }
1091        } while (0);
1092    }
1093
1094    if (property_op_type == IS_CONST &&
1095        EXPECTED(Z_OBJCE_P(object) == CACHED_PTR_EX(cache_slot))) {
1096        uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR_EX(cache_slot + 1);
1097        zend_object *zobj = Z_OBJ_P(object);
1098        zval *property;
1099
1100        if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) {
1101            property = OBJ_PROP(zobj, prop_offset);
1102            if (Z_TYPE_P(property) != IS_UNDEF) {
1103fast_assign:
1104                value = zend_assign_to_variable(property, value, value_type);
1105                if (retval && EXPECTED(!EG(exception))) {
1106                    ZVAL_COPY(retval, value);
1107                }
1108                return;
1109            }
1110        } else {
1111            if (EXPECTED(zobj->properties != NULL)) {
1112                if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) {
1113                    if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) {
1114                        GC_REFCOUNT(zobj->properties)--;
1115                    }
1116                    zobj->properties = zend_array_dup(zobj->properties);
1117                }
1118                property = zend_hash_find(zobj->properties, Z_STR_P(property_name));
1119                if (property) {
1120                    goto fast_assign;
1121                }
1122            }
1123
1124            if (!zobj->ce->__set) {
1125
1126                if (EXPECTED(zobj->properties == NULL)) {
1127                    rebuild_object_properties(zobj);
1128                }
1129                /* separate our value if necessary */
1130                if (value_type == IS_CONST) {
1131                    if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
1132                        ZVAL_COPY_VALUE(&tmp, value);
1133                        zval_copy_ctor_func(&tmp);
1134                        value = &tmp;
1135                    }
1136                } else if (value_type != IS_TMP_VAR) {
1137                    if (Z_ISREF_P(value)) {
1138                        if (value_type == IS_VAR) {
1139                            zend_reference *ref = Z_REF_P(value);
1140                            if (--(GC_REFCOUNT(ref)) == 0) {
1141                                ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value));
1142                                efree_size(ref, sizeof(zend_reference));
1143                                value = &tmp;
1144                            } else {
1145                                value = Z_REFVAL_P(value);
1146                                if (Z_REFCOUNTED_P(value)) {
1147                                    Z_ADDREF_P(value);
1148                                }
1149                            }
1150                        } else {
1151                            value = Z_REFVAL_P(value);
1152                            if (Z_REFCOUNTED_P(value)) {
1153                                Z_ADDREF_P(value);
1154                            }
1155                        }
1156                    } else if (value_type == IS_CV && Z_REFCOUNTED_P(value)) {
1157                        Z_ADDREF_P(value);
1158                    }
1159                }
1160                zend_hash_add_new(zobj->properties, Z_STR_P(property_name), value);
1161                if (retval) {
1162                    ZVAL_COPY(retval, value);
1163                }
1164                return;
1165            }
1166        }
1167    }
1168
1169    if (!Z_OBJ_HT_P(object)->write_property) {
1170        zend_error(E_WARNING, "Attempt to assign property of non-object");
1171        if (retval) {
1172            ZVAL_NULL(retval);
1173        }
1174        FREE_OP(free_value);
1175        return;
1176    }
1177
1178    /* separate our value if necessary */
1179    if (value_type == IS_CONST) {
1180        if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
1181            ZVAL_COPY_VALUE(&tmp, value);
1182            zval_copy_ctor_func(&tmp);
1183            value = &tmp;
1184        }
1185    } else if (value_type != IS_TMP_VAR) {
1186        ZVAL_DEREF(value);
1187    }
1188
1189    Z_OBJ_HT_P(object)->write_property(object, property_name, value, cache_slot);
1190
1191    if (retval && EXPECTED(!EG(exception))) {
1192        ZVAL_COPY(retval, value);
1193    }
1194    if (value_type == IS_CONST) {
1195        zval_ptr_dtor_nogc(value);
1196    } else {
1197        FREE_OP(free_value);
1198    }
1199}
1200
1201static zend_never_inline void zend_assign_to_object_dim(zval *retval, zval *object, zval *property_name, int value_type, znode_op value_op, const zend_execute_data *execute_data)
1202{
1203    zend_free_op free_value;
1204    zval *value = get_zval_ptr_deref(value_type, value_op, execute_data, &free_value, BP_VAR_R);
1205    zval tmp;
1206
1207    /* Note:  property_name in this case is really the array index! */
1208    if (!Z_OBJ_HT_P(object)->write_dimension) {
1209        zend_throw_error(NULL, "Cannot use object as array");
1210        FREE_OP(free_value);
1211        return;
1212    }
1213
1214    /* separate our value if necessary */
1215    if (value_type == IS_CONST) {
1216        if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
1217            ZVAL_COPY_VALUE(&tmp, value);
1218            zval_copy_ctor_func(&tmp);
1219            value = &tmp;
1220        }
1221    }
1222
1223    Z_OBJ_HT_P(object)->write_dimension(object, property_name, value);
1224
1225    if (retval && EXPECTED(!EG(exception))) {
1226        ZVAL_COPY(retval, value);
1227    }
1228    if (value_type == IS_CONST) {
1229        zval_ptr_dtor_nogc(value);
1230    } else {
1231        FREE_OP(free_value);
1232    }
1233}
1234
1235static zend_never_inline void zend_binary_assign_op_obj_dim(zval *object, zval *property, zval *value, zval *retval, binary_op_type binary_op)
1236{
1237    zval *z;
1238    zval rv, res;
1239
1240    if (Z_OBJ_HT_P(object)->read_dimension &&
1241        (z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R, &rv)) != NULL) {
1242
1243        if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
1244            zval rv2;
1245            zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
1246
1247            if (z == &rv) {
1248                zval_ptr_dtor(&rv);
1249            }
1250            ZVAL_COPY_VALUE(z, value);
1251        }
1252        binary_op(&res, Z_ISREF_P(z) ? Z_REFVAL_P(z) : z, value);
1253        Z_OBJ_HT_P(object)->write_dimension(object, property, &res);
1254        if (z == &rv) {
1255            zval_ptr_dtor(&rv);
1256        }
1257        if (retval) {
1258            ZVAL_COPY(retval, &res);
1259        }
1260        zval_ptr_dtor(&res);
1261    } else {
1262        zend_error(E_WARNING, "Attempt to assign property of non-object");
1263        if (retval) {
1264            ZVAL_NULL(retval);
1265        }
1266    }
1267}
1268
1269static void zend_assign_to_string_offset(zval *str, zend_long offset, zval *value, zval *result)
1270{
1271    zend_string *old_str;
1272
1273    if (offset < 0) {
1274        zend_error(E_WARNING, "Illegal string offset:  " ZEND_LONG_FMT, offset);
1275        zend_string_release(Z_STR_P(str));
1276        if (result) {
1277            ZVAL_NULL(result);
1278        }
1279        return;
1280    }
1281
1282    old_str = Z_STR_P(str);
1283    if ((size_t)offset >= Z_STRLEN_P(str)) {
1284        zend_long old_len = Z_STRLEN_P(str);
1285        Z_STR_P(str) = zend_string_extend(Z_STR_P(str), offset + 1, 0);
1286        Z_TYPE_INFO_P(str) = IS_STRING_EX;
1287        memset(Z_STRVAL_P(str) + old_len, ' ', offset - old_len);
1288        Z_STRVAL_P(str)[offset+1] = 0;
1289    } else if (!Z_REFCOUNTED_P(str)) {
1290        Z_STR_P(str) = zend_string_init(Z_STRVAL_P(str), Z_STRLEN_P(str), 0);
1291        Z_TYPE_INFO_P(str) = IS_STRING_EX;
1292    }
1293
1294    if (Z_TYPE_P(value) != IS_STRING) {
1295        zend_string *tmp = zval_get_string(value);
1296
1297        Z_STRVAL_P(str)[offset] = ZSTR_VAL(tmp)[0];
1298        zend_string_release(tmp);
1299    } else {
1300        Z_STRVAL_P(str)[offset] = Z_STRVAL_P(value)[0];
1301    }
1302    /*
1303     * the value of an assignment to a string offset is undefined
1304    T(result->u.var).var = &T->str_offset.str;
1305    */
1306
1307    zend_string_release(old_str);
1308    if (result) {
1309        zend_uchar c = (zend_uchar)Z_STRVAL_P(str)[offset];
1310
1311        if (CG(one_char_string)[c]) {
1312            ZVAL_INTERNED_STR(result, CG(one_char_string)[c]);
1313        } else {
1314            ZVAL_NEW_STR(result, zend_string_init(Z_STRVAL_P(str) + offset, 1, 0));
1315        }
1316    }
1317}
1318
1319static zend_never_inline void zend_post_incdec_overloaded_property(zval *object, zval *property, void **cache_slot, int inc, zval *result)
1320{
1321    if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
1322        zval rv, obj;
1323        zval *z;
1324        zval z_copy;
1325
1326        ZVAL_OBJ(&obj, Z_OBJ_P(object));
1327        Z_ADDREF(obj);
1328        z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, cache_slot, &rv);
1329        if (UNEXPECTED(EG(exception))) {
1330            OBJ_RELEASE(Z_OBJ(obj));
1331            return;
1332        }
1333
1334        if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
1335            zval rv2;
1336            zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
1337            if (z == &rv) {
1338                zval_ptr_dtor(&rv);
1339            }
1340            ZVAL_COPY_VALUE(z, value);
1341        }
1342        ZVAL_COPY(result, z);
1343        ZVAL_DUP(&z_copy, z);
1344        if (inc) {
1345            increment_function(&z_copy);
1346        } else {
1347            decrement_function(&z_copy);
1348        }
1349        if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z);
1350        Z_OBJ_HT(obj)->write_property(&obj, property, &z_copy, cache_slot);
1351        OBJ_RELEASE(Z_OBJ(obj));
1352        zval_ptr_dtor(&z_copy);
1353        zval_ptr_dtor(z);
1354    } else {
1355        zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
1356        ZVAL_NULL(result);
1357    }
1358}
1359
1360static zend_never_inline void zend_pre_incdec_overloaded_property(zval *object, zval *property, void **cache_slot, int inc, zval *result)
1361{
1362    zval rv;
1363
1364    if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
1365        zval *z, obj;
1366
1367        ZVAL_OBJ(&obj, Z_OBJ_P(object));
1368        Z_ADDREF(obj);
1369        z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, cache_slot, &rv);
1370        if (UNEXPECTED(EG(exception))) {
1371            OBJ_RELEASE(Z_OBJ(obj));
1372            return;
1373        }
1374
1375        if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
1376            zval rv2;
1377            zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
1378
1379            if (z == &rv) {
1380                zval_ptr_dtor(&rv);
1381            }
1382            ZVAL_COPY_VALUE(z, value);
1383        }
1384        ZVAL_DEREF(z);
1385        SEPARATE_ZVAL_NOREF(z);
1386        if (inc) {
1387            increment_function(z);
1388        } else {
1389            decrement_function(z);
1390        }
1391        if (UNEXPECTED(result)) {
1392            ZVAL_COPY(result, z);
1393        }
1394        Z_OBJ_HT(obj)->write_property(&obj, property, z, cache_slot);
1395        OBJ_RELEASE(Z_OBJ(obj));
1396        zval_ptr_dtor(z);
1397    } else {
1398        zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
1399        if (UNEXPECTED(result)) {
1400            ZVAL_NULL(result);
1401        }
1402    }
1403}
1404
1405static zend_never_inline void zend_assign_op_overloaded_property(zval *object, zval *property, void **cache_slot, zval *value, binary_op_type binary_op, zval *result)
1406{
1407    zval *z;
1408    zval rv, obj;
1409    zval *zptr;
1410
1411    ZVAL_OBJ(&obj, Z_OBJ_P(object));
1412    Z_ADDREF(obj);
1413    if (Z_OBJ_HT(obj)->read_property &&
1414        (z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, cache_slot, &rv)) != NULL) {
1415        if (UNEXPECTED(EG(exception))) {
1416            OBJ_RELEASE(Z_OBJ(obj));
1417            return;
1418        }
1419        if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
1420            zval rv2;
1421            zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
1422
1423            if (z == &rv) {
1424                zval_ptr_dtor(&rv);
1425            }
1426            ZVAL_COPY_VALUE(z, value);
1427        }
1428        zptr = z;
1429        ZVAL_DEREF(z);
1430        SEPARATE_ZVAL_NOREF(z);
1431        binary_op(z, z, value);
1432        Z_OBJ_HT(obj)->write_property(&obj, property, z, cache_slot);
1433        if (UNEXPECTED(result)) {
1434            ZVAL_COPY(result, z);
1435        }
1436        zval_ptr_dtor(zptr);
1437    } else {
1438        zend_error(E_WARNING, "Attempt to assign property of non-object");
1439        if (UNEXPECTED(result)) {
1440            ZVAL_NULL(result);
1441        }
1442    }
1443    OBJ_RELEASE(Z_OBJ(obj));
1444}
1445
1446/* Utility Functions for Extensions */
1447static void zend_extension_statement_handler(const zend_extension *extension, zend_op_array *op_array)
1448{
1449    if (extension->statement_handler) {
1450        extension->statement_handler(op_array);
1451    }
1452}
1453
1454
1455static void zend_extension_fcall_begin_handler(const zend_extension *extension, zend_op_array *op_array)
1456{
1457    if (extension->fcall_begin_handler) {
1458        extension->fcall_begin_handler(op_array);
1459    }
1460}
1461
1462
1463static void zend_extension_fcall_end_handler(const zend_extension *extension, zend_op_array *op_array)
1464{
1465    if (extension->fcall_end_handler) {
1466        extension->fcall_end_handler(op_array);
1467    }
1468}
1469
1470
1471static zend_always_inline HashTable *zend_get_target_symbol_table(zend_execute_data *execute_data, int fetch_type)
1472{
1473    HashTable *ht;
1474
1475    if (EXPECTED(fetch_type == ZEND_FETCH_GLOBAL_LOCK) ||
1476        EXPECTED(fetch_type == ZEND_FETCH_GLOBAL)) {
1477        ht = &EG(symbol_table);
1478    } else if (EXPECTED(fetch_type == ZEND_FETCH_STATIC)) {
1479        ZEND_ASSERT(EX(func)->op_array.static_variables != NULL);
1480        ht = EX(func)->op_array.static_variables;
1481        if (GC_REFCOUNT(ht) > 1) {
1482            if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
1483                GC_REFCOUNT(ht)--;
1484            }
1485            EX(func)->op_array.static_variables = ht = zend_array_dup(ht);
1486        }
1487    } else {
1488        ZEND_ASSERT(fetch_type == ZEND_FETCH_LOCAL);
1489        if (!EX(symbol_table)) {
1490            zend_rebuild_symbol_table();
1491        }
1492        ht = EX(symbol_table);
1493    }
1494    return ht;
1495}
1496
1497static zend_always_inline zval *zend_fetch_dimension_address_inner(HashTable *ht, const zval *dim, int dim_type, int type)
1498{
1499    zval *retval;
1500    zend_string *offset_key;
1501    zend_ulong hval;
1502
1503try_again:
1504    if (EXPECTED(Z_TYPE_P(dim) == IS_LONG)) {
1505        hval = Z_LVAL_P(dim);
1506num_index:
1507        retval = zend_hash_index_find(ht, hval);
1508        if (retval == NULL) {
1509            switch (type) {
1510                case BP_VAR_R:
1511                    zend_error(E_NOTICE,"Undefined offset: " ZEND_LONG_FMT, hval);
1512                    /* break missing intentionally */
1513                case BP_VAR_UNSET:
1514                case BP_VAR_IS:
1515                    retval = &EG(uninitialized_zval);
1516                    break;
1517                case BP_VAR_RW:
1518                    zend_error(E_NOTICE,"Undefined offset: " ZEND_LONG_FMT, hval);
1519                    /* break missing intentionally */
1520                case BP_VAR_W:
1521                    retval = zend_hash_index_add_new(ht, hval, &EG(uninitialized_zval));
1522                    break;
1523            }
1524        }
1525    } else if (EXPECTED(Z_TYPE_P(dim) == IS_STRING)) {
1526        offset_key = Z_STR_P(dim);
1527        if (dim_type != IS_CONST) {
1528            if (ZEND_HANDLE_NUMERIC(offset_key, hval)) {
1529                goto num_index;
1530            }
1531        }
1532str_index:
1533        retval = zend_hash_find(ht, offset_key);
1534        if (retval) {
1535            /* support for $GLOBALS[...] */
1536            if (UNEXPECTED(Z_TYPE_P(retval) == IS_INDIRECT)) {
1537                retval = Z_INDIRECT_P(retval);
1538                if (UNEXPECTED(Z_TYPE_P(retval) == IS_UNDEF)) {
1539                    switch (type) {
1540                        case BP_VAR_R:
1541                            zend_error(E_NOTICE, "Undefined index: %s", ZSTR_VAL(offset_key));
1542                            /* break missing intentionally */
1543                        case BP_VAR_UNSET:
1544                        case BP_VAR_IS:
1545                            retval = &EG(uninitialized_zval);
1546                            break;
1547                        case BP_VAR_RW:
1548                            zend_error(E_NOTICE,"Undefined index: %s", ZSTR_VAL(offset_key));
1549                            /* break missing intentionally */
1550                        case BP_VAR_W:
1551                            ZVAL_NULL(retval);
1552                            break;
1553                    }
1554                }
1555            }
1556        } else {
1557            switch (type) {
1558                case BP_VAR_R:
1559                    zend_error(E_NOTICE, "Undefined index: %s", ZSTR_VAL(offset_key));
1560                    /* break missing intentionally */
1561                case BP_VAR_UNSET:
1562                case BP_VAR_IS:
1563                    retval = &EG(uninitialized_zval);
1564                    break;
1565                case BP_VAR_RW:
1566                    zend_error(E_NOTICE,"Undefined index: %s", ZSTR_VAL(offset_key));
1567                    /* break missing intentionally */
1568                case BP_VAR_W:
1569                    retval = zend_hash_add_new(ht, offset_key, &EG(uninitialized_zval));
1570                    break;
1571            }
1572        }
1573    } else {
1574        switch (Z_TYPE_P(dim)) {
1575            case IS_NULL:
1576                offset_key = ZSTR_EMPTY_ALLOC();
1577                goto str_index;
1578            case IS_DOUBLE:
1579                hval = zend_dval_to_lval(Z_DVAL_P(dim));
1580                goto num_index;
1581            case IS_RESOURCE:
1582                zend_error(E_NOTICE, "Resource ID#%pd used as offset, casting to integer (%pd)", Z_RES_HANDLE_P(dim), Z_RES_HANDLE_P(dim));
1583                hval = Z_RES_HANDLE_P(dim);
1584                goto num_index;
1585            case IS_FALSE:
1586                hval = 0;
1587                goto num_index;
1588            case IS_TRUE:
1589                hval = 1;
1590                goto num_index;
1591            case IS_REFERENCE:
1592                dim = Z_REFVAL_P(dim);
1593                goto try_again;
1594            default:
1595                zend_error(E_WARNING, "Illegal offset type");
1596                retval = (type == BP_VAR_W || type == BP_VAR_RW) ?
1597                    &EG(error_zval) : &EG(uninitialized_zval);
1598        }
1599    }
1600    return retval;
1601}
1602
1603static zend_never_inline zend_long zend_check_string_offset(zval *dim, int type)
1604{
1605    zend_long offset;
1606
1607try_again:
1608    if (UNEXPECTED(Z_TYPE_P(dim) != IS_LONG)) {
1609        switch(Z_TYPE_P(dim)) {
1610            case IS_STRING:
1611                if (IS_LONG == is_numeric_string(Z_STRVAL_P(dim), Z_STRLEN_P(dim), NULL, NULL, -1)) {
1612                    break;
1613                }
1614                if (type != BP_VAR_UNSET) {
1615                    zend_error(E_WARNING, "Illegal string offset '%s'", Z_STRVAL_P(dim));
1616                }
1617                break;
1618            case IS_DOUBLE:
1619            case IS_NULL:
1620            case IS_FALSE:
1621            case IS_TRUE:
1622                zend_error(E_NOTICE, "String offset cast occurred");
1623                break;
1624            case IS_REFERENCE:
1625                dim = Z_REFVAL_P(dim);
1626                goto try_again;
1627            default:
1628                zend_error(E_WARNING, "Illegal offset type");
1629                break;
1630        }
1631
1632        offset = zval_get_long(dim);
1633    } else {
1634        offset = Z_LVAL_P(dim);
1635    }
1636
1637    return offset;
1638}
1639
1640static zend_always_inline zend_long zend_fetch_string_offset(zval *container, zval *dim, int type)
1641{
1642    zend_long offset = zend_check_string_offset(dim, type);
1643
1644    if (Z_REFCOUNTED_P(container)) {
1645        if (Z_REFCOUNT_P(container) > 1) {
1646            Z_DELREF_P(container);
1647            zval_copy_ctor_func(container);
1648        }
1649        Z_ADDREF_P(container);
1650    }
1651    return offset;
1652}
1653
1654static zend_always_inline void zend_fetch_dimension_address(zval *result, zval *container, zval *dim, int dim_type, int type)
1655{
1656    zval *retval;
1657
1658    if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
1659try_array:
1660        SEPARATE_ARRAY(container);
1661fetch_from_array:
1662        if (dim == NULL) {
1663            retval = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval));
1664            if (UNEXPECTED(retval == NULL)) {
1665                zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied");
1666                retval = &EG(error_zval);
1667            }
1668        } else {
1669            retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, dim_type, type);
1670        }
1671        ZVAL_INDIRECT(result, retval);
1672        return;
1673    } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) {
1674        container = Z_REFVAL_P(container);
1675        if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
1676            goto try_array;
1677        }
1678    }
1679    if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) {
1680        if (type != BP_VAR_UNSET && UNEXPECTED(Z_STRLEN_P(container) == 0)) {
1681            zval_ptr_dtor_nogc(container);
1682convert_to_array:
1683            ZVAL_NEW_ARR(container);
1684            zend_hash_init(Z_ARRVAL_P(container), 8, NULL, ZVAL_PTR_DTOR, 0);
1685            goto fetch_from_array;
1686        }
1687
1688        if (dim == NULL) {
1689            zend_throw_error(NULL, "[] operator not supported for strings");
1690            ZVAL_INDIRECT(result, &EG(error_zval));
1691        } else {
1692            zend_check_string_offset(dim, type);
1693            ZVAL_INDIRECT(result, NULL); /* wrong string offset */
1694        }
1695    } else if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
1696        if (!Z_OBJ_HT_P(container)->read_dimension) {
1697            zend_throw_error(NULL, "Cannot use object as array");
1698            retval = &EG(error_zval);
1699        } else {
1700            retval = Z_OBJ_HT_P(container)->read_dimension(container, dim, type, result);
1701
1702            if (UNEXPECTED(retval == &EG(uninitialized_zval))) {
1703                zend_class_entry *ce = Z_OBJCE_P(container);
1704
1705                ZVAL_NULL(result);
1706                zend_error(E_NOTICE, "Indirect modification of overloaded element of %s has no effect", ZSTR_VAL(ce->name));
1707            } else if (EXPECTED(retval && Z_TYPE_P(retval) != IS_UNDEF)) {
1708                if (!Z_ISREF_P(retval)) {
1709                    if (Z_REFCOUNTED_P(retval) &&
1710                        Z_REFCOUNT_P(retval) > 1) {
1711                        if (Z_TYPE_P(retval) != IS_OBJECT) {
1712                            Z_DELREF_P(retval);
1713                            ZVAL_DUP(result, retval);
1714                            retval = result;
1715                        } else {
1716                            ZVAL_COPY(result, retval);
1717                            retval = result;
1718                        }
1719                    }
1720                    if (Z_TYPE_P(retval) != IS_OBJECT) {
1721                        zend_class_entry *ce = Z_OBJCE_P(container);
1722                        zend_error(E_NOTICE, "Indirect modification of overloaded element of %s has no effect", ZSTR_VAL(ce->name));
1723                    }
1724                }
1725                if (result != retval) {
1726                    ZVAL_INDIRECT(result, retval);
1727                }
1728            } else {
1729                ZVAL_INDIRECT(result, &EG(error_zval));
1730            }
1731        }
1732    } else if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) {
1733        if (UNEXPECTED(container == &EG(error_zval))) {
1734            ZVAL_INDIRECT(result, &EG(error_zval));
1735        } else if (type != BP_VAR_UNSET) {
1736            goto convert_to_array;
1737        } else {
1738            /* for read-mode only */
1739            ZVAL_NULL(result);
1740        }
1741    } else {
1742        if (type == BP_VAR_UNSET) {
1743            zend_error(E_WARNING, "Cannot unset offset in a non-array variable");
1744            ZVAL_NULL(result);
1745        } else {
1746            zend_error(E_WARNING, "Cannot use a scalar value as an array");
1747            ZVAL_INDIRECT(result, &EG(error_zval));
1748        }
1749    }
1750}
1751
1752static zend_never_inline void zend_fetch_dimension_address_W(zval *result, zval *container_ptr, zval *dim, int dim_type)
1753{
1754    zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_W);
1755}
1756
1757static zend_never_inline void zend_fetch_dimension_address_RW(zval *result, zval *container_ptr, zval *dim, int dim_type)
1758{
1759    zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_RW);
1760}
1761
1762static zend_never_inline void zend_fetch_dimension_address_UNSET(zval *result, zval *container_ptr, zval *dim, int dim_type)
1763{
1764    zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_UNSET);
1765}
1766
1767static zend_always_inline void zend_fetch_dimension_address_read(zval *result, zval *container, zval *dim, int dim_type, int type)
1768{
1769    zval *retval;
1770
1771    if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
1772try_array:
1773        retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, dim_type, type);
1774        ZVAL_COPY(result, retval);
1775        return;
1776    } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) {
1777        container = Z_REFVAL_P(container);
1778        if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
1779            goto try_array;
1780        }
1781    }
1782    if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) {
1783        zend_long offset;
1784
1785try_string_offset:
1786        if (UNEXPECTED(Z_TYPE_P(dim) != IS_LONG)) {
1787            switch(Z_TYPE_P(dim)) {
1788                /* case IS_LONG: */
1789                case IS_STRING:
1790                    if (IS_LONG == is_numeric_string(Z_STRVAL_P(dim), Z_STRLEN_P(dim), NULL, NULL, -1)) {
1791                        break;
1792                    }
1793                    if (type == BP_VAR_IS) {
1794                        ZVAL_NULL(result);
1795                        return;
1796                    }
1797                    zend_error(E_WARNING, "Illegal string offset '%s'", Z_STRVAL_P(dim));
1798                    break;
1799                case IS_DOUBLE:
1800                case IS_NULL:
1801                case IS_FALSE:
1802                case IS_TRUE:
1803                    if (type != BP_VAR_IS) {
1804                        zend_error(E_NOTICE, "String offset cast occurred");
1805                    }
1806                    break;
1807                case IS_REFERENCE:
1808                    dim = Z_REFVAL_P(dim);
1809                    goto try_string_offset;
1810                default:
1811                    zend_error(E_WARNING, "Illegal offset type");
1812                    break;
1813            }
1814
1815            offset = zval_get_long(dim);
1816        } else {
1817            offset = Z_LVAL_P(dim);
1818        }
1819
1820        if (UNEXPECTED(offset < 0) || UNEXPECTED(Z_STRLEN_P(container) <= (size_t)offset)) {
1821            if (type != BP_VAR_IS) {
1822                zend_error(E_NOTICE, "Uninitialized string offset: %pd", offset);
1823                ZVAL_EMPTY_STRING(result);
1824            } else {
1825                ZVAL_NULL(result);
1826            }
1827        } else {
1828            zend_uchar c = (zend_uchar)Z_STRVAL_P(container)[offset];
1829
1830            if (CG(one_char_string)[c]) {
1831                ZVAL_INTERNED_STR(result, CG(one_char_string)[c]);
1832            } else {
1833                ZVAL_NEW_STR(result, zend_string_init(Z_STRVAL_P(container) + offset, 1, 0));
1834            }
1835        }
1836    } else if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
1837        if (!Z_OBJ_HT_P(container)->read_dimension) {
1838            zend_throw_error(NULL, "Cannot use object as array");
1839            ZVAL_NULL(result);
1840        } else {
1841            retval = Z_OBJ_HT_P(container)->read_dimension(container, dim, type, result);
1842
1843            ZEND_ASSERT(result != NULL);
1844            if (retval) {
1845                if (result != retval) {
1846                    ZVAL_COPY(result, retval);
1847                }
1848            } else {
1849                ZVAL_NULL(result);
1850            }
1851        }
1852    } else {
1853        ZVAL_NULL(result);
1854    }
1855}
1856
1857static zend_never_inline void zend_fetch_dimension_address_read_R(zval *result, zval *container, zval *dim, int dim_type)
1858{
1859    zend_fetch_dimension_address_read(result, container, dim, dim_type, BP_VAR_R);
1860}
1861
1862static zend_never_inline void zend_fetch_dimension_address_read_IS(zval *result, zval *container, zval *dim, int dim_type)
1863{
1864    zend_fetch_dimension_address_read(result, container, dim, dim_type, BP_VAR_IS);
1865}
1866
1867ZEND_API void zend_fetch_dimension_by_zval(zval *result, zval *container, zval *dim)
1868{
1869    zend_fetch_dimension_address_read_R(result, container, dim, IS_TMP_VAR);
1870}
1871
1872static zend_always_inline void zend_fetch_property_address(zval *result, zval *container, uint32_t container_op_type, zval *prop_ptr, uint32_t prop_op_type, void **cache_slot, int type)
1873{
1874    if (container_op_type != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
1875        do {
1876            if (container_op_type == IS_VAR && UNEXPECTED(container == &EG(error_zval))) {
1877                ZVAL_INDIRECT(result, &EG(error_zval));
1878                return;
1879            }
1880
1881            if (Z_ISREF_P(container)) {
1882                container = Z_REFVAL_P(container);
1883                if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
1884                    break;
1885                }
1886            }
1887
1888            /* this should modify object only if it's empty */
1889            if (type != BP_VAR_UNSET &&
1890                EXPECTED(Z_TYPE_P(container) <= IS_FALSE ||
1891                  (Z_TYPE_P(container) == IS_STRING && Z_STRLEN_P(container)==0))) {
1892                zval_ptr_dtor_nogc(container);
1893                object_init(container);
1894            } else {
1895                zend_error(E_WARNING, "Attempt to modify property of non-object");
1896                ZVAL_INDIRECT(result, &EG(error_zval));
1897                return;
1898            }
1899        } while (0);
1900    }
1901    if (prop_op_type == IS_CONST &&
1902        EXPECTED(Z_OBJCE_P(container) == CACHED_PTR_EX(cache_slot))) {
1903        uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR_EX(cache_slot + 1);
1904        zend_object *zobj = Z_OBJ_P(container);
1905        zval *retval;
1906
1907        if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) {
1908            retval = OBJ_PROP(zobj, prop_offset);
1909            if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
1910                ZVAL_INDIRECT(result, retval);
1911                return;
1912            }
1913        } else if (EXPECTED(zobj->properties != NULL)) {
1914            retval = zend_hash_find(zobj->properties, Z_STR_P(prop_ptr));
1915            if (EXPECTED(retval)) {
1916                ZVAL_INDIRECT(result, retval);
1917                return;
1918            }
1919        }
1920    }
1921    if (EXPECTED(Z_OBJ_HT_P(container)->get_property_ptr_ptr)) {
1922        zval *ptr = Z_OBJ_HT_P(container)->get_property_ptr_ptr(container, prop_ptr, type, cache_slot);
1923        if (NULL == ptr) {
1924            if (Z_OBJ_HT_P(container)->read_property &&
1925                (ptr = Z_OBJ_HT_P(container)->read_property(container, prop_ptr, type, cache_slot, result)) != NULL) {
1926                if (ptr != result) {
1927                    ZVAL_INDIRECT(result, ptr);
1928                }
1929            } else {
1930                zend_throw_error(NULL, "Cannot access undefined property for object with overloaded property access");
1931                ZVAL_INDIRECT(result, &EG(error_zval));
1932            }
1933        } else {
1934            ZVAL_INDIRECT(result, ptr);
1935        }
1936    } else if (EXPECTED(Z_OBJ_HT_P(container)->read_property)) {
1937        zval *ptr = Z_OBJ_HT_P(container)->read_property(container, prop_ptr, type, cache_slot, result);
1938        if (ptr != result) {
1939            ZVAL_INDIRECT(result, ptr);
1940        }
1941    } else {
1942        zend_error(E_WARNING, "This object doesn't support property references");
1943        ZVAL_INDIRECT(result, &EG(error_zval));
1944    }
1945}
1946
1947static 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)
1948{
1949    zend_brk_cont_element *jmp_to;
1950
1951    do {
1952        ZEND_ASSERT(array_offset != -1);
1953        jmp_to = &op_array->brk_cont_array[array_offset];
1954        if (nest_levels > 1 && jmp_to->start >= 0) {
1955            zend_op *brk_opline = &op_array->opcodes[jmp_to->brk];
1956
1957            if (brk_opline->opcode == ZEND_FREE) {
1958                zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var));
1959            } else if (brk_opline->opcode == ZEND_FE_FREE) {
1960                zval *var = EX_VAR(brk_opline->op1.var);
1961                if (Z_TYPE_P(var) != IS_ARRAY && Z_FE_ITER_P(var) != (uint32_t)-1) {
1962                    zend_hash_iterator_del(Z_FE_ITER_P(var));
1963                }
1964                zval_ptr_dtor_nogc(var);
1965            }
1966        }
1967        array_offset = jmp_to->parent;
1968    } while (--nest_levels > 0);
1969    return jmp_to;
1970}
1971
1972#if ZEND_INTENSIVE_DEBUGGING
1973
1974#define CHECK_SYMBOL_TABLES()                                                   \
1975    zend_hash_apply(&EG(symbol_table), zend_check_symbol);          \
1976    if (&EG(symbol_table)!=EX(symbol_table)) {                          \
1977        zend_hash_apply(EX(symbol_table), zend_check_symbol);   \
1978    }
1979
1980static int zend_check_symbol(zval *pz)
1981{
1982    if (Z_TYPE_P(pz) == IS_INDIRECT) {
1983        pz = Z_INDIRECT_P(pz);
1984    }
1985    if (Z_TYPE_P(pz) > 10) {
1986        fprintf(stderr, "Warning!  %x has invalid type!\n", *pz);
1987/* See http://support.microsoft.com/kb/190351 */
1988#ifdef ZEND_WIN32
1989        fflush(stderr);
1990#endif
1991    } else if (Z_TYPE_P(pz) == IS_ARRAY) {
1992        zend_hash_apply(Z_ARRVAL_P(pz), zend_check_symbol);
1993    } else if (Z_TYPE_P(pz) == IS_OBJECT) {
1994        /* OBJ-TBI - doesn't support new object model! */
1995        zend_hash_apply(Z_OBJPROP_P(pz), zend_check_symbol);
1996    }
1997
1998    return 0;
1999}
2000
2001
2002#else
2003#define CHECK_SYMBOL_TABLES()
2004#endif
2005
2006ZEND_API void execute_internal(zend_execute_data *execute_data, zval *return_value)
2007{
2008    execute_data->func->internal_function.handler(execute_data, return_value);
2009}
2010
2011ZEND_API void zend_clean_and_cache_symbol_table(zend_array *symbol_table) /* {{{ */
2012{
2013    if (EG(symtable_cache_ptr) >= EG(symtable_cache_limit)) {
2014        zend_array_destroy(symbol_table);
2015    } else {
2016        /* clean before putting into the cache, since clean
2017           could call dtors, which could use cached hash */
2018        zend_symtable_clean(symbol_table);
2019        *(++EG(symtable_cache_ptr)) = symbol_table;
2020    }
2021}
2022/* }}} */
2023
2024static zend_always_inline void i_free_compiled_variables(zend_execute_data *execute_data) /* {{{ */
2025{
2026    zval *cv = EX_VAR_NUM(0);
2027    zval *end = cv + EX(func)->op_array.last_var;
2028    while (EXPECTED(cv != end)) {
2029        if (Z_REFCOUNTED_P(cv)) {
2030            if (!Z_DELREF_P(cv)) {
2031                zend_refcounted *r = Z_COUNTED_P(cv);
2032                ZVAL_NULL(cv);
2033                zval_dtor_func_for_ptr(r);
2034            } else {
2035                GC_ZVAL_CHECK_POSSIBLE_ROOT(cv);
2036            }
2037        }
2038        cv++;
2039    }
2040}
2041/* }}} */
2042
2043void zend_free_compiled_variables(zend_execute_data *execute_data) /* {{{ */
2044{
2045    i_free_compiled_variables(execute_data);
2046}
2047/* }}} */
2048
2049#ifdef ZEND_WIN32
2050# define ZEND_VM_INTERRUPT_CHECK() do { \
2051        if (EG(timed_out)) { \
2052            zend_timeout(0); \
2053        } \
2054    } while (0)
2055#else
2056# define ZEND_VM_INTERRUPT_CHECK() do { \
2057    } while (0)
2058#endif
2059
2060/*
2061 * Stack Frame Layout (the whole stack frame is allocated at once)
2062 * ==================
2063 *
2064 *                             +========================================+
2065 * EG(current_execute_data) -> | zend_execute_data                      |
2066 *                             +----------------------------------------+
2067 *     EX_CV_NUM(0) ---------> | VAR[0] = ARG[1]                        |
2068 *                             | ...                                    |
2069 *                             | VAR[op_array->num_args-1] = ARG[N]     |
2070 *                             | ...                                    |
2071 *                             | VAR[op_array->last_var-1]              |
2072 *                             | VAR[op_array->last_var] = TMP[0]       |
2073 *                             | ...                                    |
2074 *                             | VAR[op_array->last_var+op_array->T-1]  |
2075 *                             | ARG[N+1] (extra_args)                  |
2076 *                             | ...                                    |
2077 *                             +----------------------------------------+
2078 */
2079
2080static zend_always_inline void i_init_func_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value, int check_this) /* {{{ */
2081{
2082    uint32_t first_extra_arg, num_args;
2083    ZEND_ASSERT(EX(func) == (zend_function*)op_array);
2084
2085    EX(opline) = op_array->opcodes;
2086    EX(call) = NULL;
2087    EX(return_value) = return_value;
2088
2089    /* Handle arguments */
2090    first_extra_arg = op_array->num_args;
2091    num_args = EX_NUM_ARGS();
2092    if (UNEXPECTED(num_args > first_extra_arg)) {
2093        zval *end, *src, *dst;
2094        uint32_t type_flags = 0;
2095
2096        if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) {
2097            /* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */
2098            EX(opline) += first_extra_arg;
2099        }
2100
2101        /* move extra args into separate array after all CV and TMP vars */
2102        end = EX_VAR_NUM(first_extra_arg - 1);
2103        src = end + (num_args - first_extra_arg);
2104        dst = src + (op_array->last_var + op_array->T - first_extra_arg);
2105        if (EXPECTED(src != dst)) {
2106            do {
2107                type_flags |= Z_TYPE_INFO_P(src);
2108                ZVAL_COPY_VALUE(dst, src);
2109                ZVAL_UNDEF(src);
2110                src--;
2111                dst--;
2112            } while (src != end);
2113        } else {
2114            do {
2115                type_flags |= Z_TYPE_INFO_P(src);
2116                src--;
2117            } while (src != end);
2118        }
2119        ZEND_ADD_CALL_FLAG(execute_data, ((type_flags >> Z_TYPE_FLAGS_SHIFT) & IS_TYPE_REFCOUNTED));
2120    } else if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) {
2121        /* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */
2122        EX(opline) += num_args;
2123    }
2124
2125    /* Initialize CV variables (skip arguments) */
2126    if (EXPECTED((int)num_args < op_array->last_var)) {
2127        zval *var = EX_VAR_NUM(num_args);
2128        zval *end = EX_VAR_NUM(op_array->last_var);
2129
2130        do {
2131            ZVAL_UNDEF(var);
2132            var++;
2133        } while (var != end);
2134    }
2135
2136    if (check_this && op_array->this_var != (uint32_t)-1 && EXPECTED(Z_OBJ(EX(This)))) {
2137        ZVAL_OBJ(EX_VAR(op_array->this_var), Z_OBJ(EX(This)));
2138        GC_REFCOUNT(Z_OBJ(EX(This)))++;
2139    }
2140
2141    if (UNEXPECTED(!op_array->run_time_cache)) {
2142        op_array->run_time_cache = zend_arena_alloc(&CG(arena), op_array->cache_size);
2143        memset(op_array->run_time_cache, 0, op_array->cache_size);
2144    }
2145    EX_LOAD_RUN_TIME_CACHE(op_array);
2146    EX_LOAD_LITERALS(op_array);
2147
2148    EG(current_execute_data) = execute_data;
2149    ZEND_VM_INTERRUPT_CHECK();
2150}
2151/* }}} */
2152
2153static zend_always_inline void i_init_code_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value) /* {{{ */
2154{
2155    ZEND_ASSERT(EX(func) == (zend_function*)op_array);
2156
2157    EX(opline) = op_array->opcodes;
2158    EX(call) = NULL;
2159    EX(return_value) = return_value;
2160
2161    zend_attach_symbol_table(execute_data);
2162
2163    if (op_array->this_var != (uint32_t)-1 && EXPECTED(Z_OBJ(EX(This)))) {
2164        ZVAL_OBJ(EX_VAR(op_array->this_var), Z_OBJ(EX(This)));
2165        GC_REFCOUNT(Z_OBJ(EX(This)))++;
2166    }
2167
2168    if (!op_array->run_time_cache) {
2169        op_array->run_time_cache = emalloc(op_array->cache_size);
2170        memset(op_array->run_time_cache, 0, op_array->cache_size);
2171    }
2172    EX_LOAD_RUN_TIME_CACHE(op_array);
2173    EX_LOAD_LITERALS(op_array);
2174
2175    EG(current_execute_data) = execute_data;
2176    ZEND_VM_INTERRUPT_CHECK();
2177}
2178/* }}} */
2179
2180static zend_always_inline void i_init_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value) /* {{{ */
2181{
2182    ZEND_ASSERT(EX(func) == (zend_function*)op_array);
2183
2184    EX(opline) = op_array->opcodes;
2185    EX(call) = NULL;
2186    EX(return_value) = return_value;
2187
2188    if (UNEXPECTED(EX(symbol_table) != NULL)) {
2189        zend_attach_symbol_table(execute_data);
2190    } else {
2191        uint32_t first_extra_arg, num_args;
2192
2193        /* Handle arguments */
2194        first_extra_arg = op_array->num_args;
2195        num_args = EX_NUM_ARGS();
2196        if (UNEXPECTED(num_args > first_extra_arg)) {
2197            zval *end, *src, *dst;
2198            uint32_t type_flags = 0;
2199
2200            if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) {
2201                /* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */
2202                EX(opline) += first_extra_arg;
2203            }
2204
2205            /* move extra args into separate array after all CV and TMP vars */
2206            end = EX_VAR_NUM(first_extra_arg - 1);
2207            src = end + (num_args - first_extra_arg);
2208            dst = src + (op_array->last_var + op_array->T - first_extra_arg);
2209            if (EXPECTED(src != dst)) {
2210                do {
2211                    type_flags |= Z_TYPE_INFO_P(src);
2212                    ZVAL_COPY_VALUE(dst, src);
2213                    ZVAL_UNDEF(src);
2214                    src--;
2215                    dst--;
2216                } while (src != end);
2217            } else {
2218                do {
2219                    type_flags |= Z_TYPE_INFO_P(src);
2220                    src--;
2221                } while (src != end);
2222            }
2223            ZEND_ADD_CALL_FLAG(execute_data, ((type_flags >> Z_TYPE_FLAGS_SHIFT) & IS_TYPE_REFCOUNTED));
2224        } else if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) {
2225            /* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */
2226            EX(opline) += num_args;
2227        }
2228
2229        /* Initialize CV variables (skip arguments) */
2230        if (EXPECTED((int)num_args < op_array->last_var)) {
2231            zval *var = EX_VAR_NUM(num_args);
2232            zval *end = EX_VAR_NUM(op_array->last_var);
2233
2234            do {
2235                ZVAL_UNDEF(var);
2236                var++;
2237            } while (var != end);
2238        }
2239    }
2240
2241    if (op_array->this_var != (uint32_t)-1 && EXPECTED(Z_OBJ(EX(This)))) {
2242        ZVAL_OBJ(EX_VAR(op_array->this_var), Z_OBJ(EX(This)));
2243        GC_REFCOUNT(Z_OBJ(EX(This)))++;
2244    }
2245
2246    if (!op_array->run_time_cache) {
2247        if (op_array->function_name) {
2248            op_array->run_time_cache = zend_arena_alloc(&CG(arena), op_array->cache_size);
2249        } else {
2250            op_array->run_time_cache = emalloc(op_array->cache_size);
2251        }
2252        memset(op_array->run_time_cache, 0, op_array->cache_size);
2253    }
2254    EX_LOAD_RUN_TIME_CACHE(op_array);
2255    EX_LOAD_LITERALS(op_array);
2256
2257    EG(current_execute_data) = execute_data;
2258    ZEND_VM_INTERRUPT_CHECK();
2259}
2260/* }}} */
2261
2262ZEND_API zend_execute_data *zend_create_generator_execute_data(zend_execute_data *call, zend_op_array *op_array, zval *return_value) /* {{{ */
2263{
2264    /*
2265     * Normally the execute_data is allocated on the VM stack (because it does
2266     * not actually do any allocation and thus is faster). For generators
2267     * though this behavior would be suboptimal, because the (rather large)
2268     * structure would have to be copied back and forth every time execution is
2269     * suspended or resumed. That's why for generators the execution context
2270     * is allocated using a separate VM stack, thus allowing to save and
2271     * restore it simply by replacing a pointer.
2272     */
2273    zend_execute_data *execute_data;
2274    uint32_t num_args = ZEND_CALL_NUM_ARGS(call);
2275    size_t stack_size = (ZEND_CALL_FRAME_SLOT + MAX(op_array->last_var + op_array->T, num_args)) * sizeof(zval);
2276    uint32_t call_info;
2277
2278    EG(vm_stack) = zend_vm_stack_new_page(
2279        EXPECTED(stack_size < ZEND_VM_STACK_FREE_PAGE_SIZE(1)) ?
2280            ZEND_VM_STACK_PAGE_SIZE(1) :
2281            ZEND_VM_STACK_PAGE_ALIGNED_SIZE(1, stack_size),
2282        NULL);
2283    EG(vm_stack_top) = EG(vm_stack)->top;
2284    EG(vm_stack_end) = EG(vm_stack)->end;
2285
2286    call_info = ZEND_CALL_TOP_FUNCTION | ZEND_CALL_ALLOCATED | (ZEND_CALL_INFO(call) & (ZEND_CALL_CLOSURE|ZEND_CALL_RELEASE_THIS));
2287    if (Z_OBJ(call->This)) {
2288        call_info |= ZEND_CALL_RELEASE_THIS;
2289    }
2290    execute_data = zend_vm_stack_push_call_frame(
2291        call_info,
2292        (zend_function*)op_array,
2293        num_args,
2294        call->called_scope,
2295        Z_OBJ(call->This));
2296    EX(prev_execute_data) = NULL;
2297    EX_NUM_ARGS() = num_args;
2298
2299    /* copy arguments */
2300    if (num_args > 0) {
2301        zval *arg_src = ZEND_CALL_ARG(call, 1);
2302        zval *arg_dst = ZEND_CALL_ARG(execute_data, 1);
2303        zval *end = arg_src + num_args;
2304
2305        do {
2306            ZVAL_COPY_VALUE(arg_dst, arg_src);
2307            arg_src++;
2308            arg_dst++;
2309        } while (arg_src != end);
2310    }
2311
2312    EX(symbol_table) = NULL;
2313
2314    i_init_func_execute_data(execute_data, op_array, return_value, 1);
2315
2316    return execute_data;
2317}
2318/* }}} */
2319
2320ZEND_API void zend_init_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value) /* {{{ */
2321{
2322    EX(prev_execute_data) = EG(current_execute_data);
2323    i_init_execute_data(execute_data, op_array, return_value);
2324}
2325/* }}} */
2326
2327static zend_always_inline zend_bool zend_is_by_ref_func_arg_fetch(const zend_op *opline, zend_execute_data *call) /* {{{ */
2328{
2329    uint32_t arg_num = opline->extended_value & ZEND_FETCH_ARG_MASK;
2330    return ARG_SHOULD_BE_SENT_BY_REF(call->func, arg_num);
2331}
2332/* }}} */
2333
2334static zend_execute_data *zend_vm_stack_copy_call_frame(zend_execute_data *call, uint32_t passed_args, uint32_t additional_args) /* {{{ */
2335{
2336    zend_execute_data *new_call;
2337    int used_stack = (EG(vm_stack_top) - (zval*)call) + additional_args;
2338
2339    /* copy call frame into new stack segment */
2340    new_call = zend_vm_stack_extend(used_stack * sizeof(zval));
2341    *new_call = *call;
2342    ZEND_SET_CALL_INFO(new_call, ZEND_CALL_INFO(new_call) | ZEND_CALL_ALLOCATED);
2343
2344    if (passed_args) {
2345        zval *src = ZEND_CALL_ARG(call, 1);
2346        zval *dst = ZEND_CALL_ARG(new_call, 1);
2347        do {
2348            ZVAL_COPY_VALUE(dst, src);
2349            passed_args--;
2350            src++;
2351            dst++;
2352        } while (passed_args);
2353    }
2354
2355    /* delete old call_frame from previous stack segment */
2356    EG(vm_stack)->prev->top = (zval*)call;
2357
2358    /* delete previous stack segment if it becames empty */
2359    if (UNEXPECTED(EG(vm_stack)->prev->top == ZEND_VM_STACK_ELEMETS(EG(vm_stack)->prev))) {
2360        zend_vm_stack r = EG(vm_stack)->prev;
2361
2362        EG(vm_stack)->prev = r->prev;
2363        efree(r);
2364    }
2365
2366    return new_call;
2367}
2368/* }}} */
2369
2370static zend_always_inline void zend_vm_stack_extend_call_frame(zend_execute_data **call, uint32_t passed_args, uint32_t additional_args) /* {{{ */
2371{
2372    if (EXPECTED((uint32_t)(EG(vm_stack_end) - EG(vm_stack_top)) > additional_args)) {
2373        EG(vm_stack_top) += additional_args;
2374    } else {
2375        *call = zend_vm_stack_copy_call_frame(*call, passed_args, additional_args);
2376    }
2377}
2378/* }}} */
2379
2380static zend_always_inline zend_generator *zend_get_running_generator(zend_execute_data *execute_data) /* {{{ */
2381{
2382    /* The generator object is stored in EX(return_value) */
2383    zend_generator *generator = (zend_generator *) EX(return_value);
2384    /* However control may currently be delegated to another generator.
2385     * That's the one we're interested in. */
2386    return generator;
2387}
2388/* }}} */
2389
2390static zend_always_inline void i_cleanup_unfinished_execution(zend_execute_data *execute_data, uint32_t op_num, uint32_t catch_op_num) /* {{{ */
2391{
2392    int i;
2393    if (UNEXPECTED(EX(call))) {
2394        zend_execute_data *call = EX(call);
2395        zend_op *opline = EX(func)->op_array.opcodes + op_num;
2396        int level;
2397        int do_exit;
2398
2399        if (UNEXPECTED(opline->opcode == ZEND_INIT_FCALL ||
2400            opline->opcode == ZEND_INIT_FCALL_BY_NAME ||
2401            opline->opcode == ZEND_INIT_DYNAMIC_CALL ||
2402            opline->opcode == ZEND_INIT_METHOD_CALL ||
2403            opline->opcode == ZEND_INIT_STATIC_METHOD_CALL)) {
2404            ZEND_ASSERT(op_num);
2405            opline--;
2406        }
2407
2408        do {
2409            /* If the exception was thrown during a function call there might be
2410             * arguments pushed to the stack that have to be dtor'ed. */
2411
2412            /* find the number of actually passed arguments */
2413            level = 0;
2414            do_exit = 0;
2415            do {
2416                switch (opline->opcode) {
2417                    case ZEND_DO_FCALL:
2418                    case ZEND_DO_ICALL:
2419                    case ZEND_DO_UCALL:
2420                    case ZEND_DO_FCALL_BY_NAME:
2421                        level++;
2422                        break;
2423                    case ZEND_INIT_FCALL:
2424                    case ZEND_INIT_FCALL_BY_NAME:
2425                    case ZEND_INIT_NS_FCALL_BY_NAME:
2426                    case ZEND_INIT_DYNAMIC_CALL:
2427                    case ZEND_INIT_USER_CALL:
2428                    case ZEND_INIT_METHOD_CALL:
2429                    case ZEND_INIT_STATIC_METHOD_CALL:
2430                    case ZEND_NEW:
2431                        if (level == 0) {
2432                            ZEND_CALL_NUM_ARGS(call) = 0;
2433                            do_exit = 1;
2434                        }
2435                        level--;
2436                        break;
2437                    case ZEND_SEND_VAL:
2438                    case ZEND_SEND_VAL_EX:
2439                    case ZEND_SEND_VAR:
2440                    case ZEND_SEND_VAR_EX:
2441                    case ZEND_SEND_REF:
2442                    case ZEND_SEND_VAR_NO_REF:
2443                    case ZEND_SEND_USER:
2444                        if (level == 0) {
2445                            ZEND_CALL_NUM_ARGS(call) = opline->op2.num;
2446                            do_exit = 1;
2447                        }
2448                        break;
2449                    case ZEND_SEND_ARRAY:
2450                    case ZEND_SEND_UNPACK:
2451                        if (level == 0) {
2452                            do_exit = 1;
2453                        }
2454                        break;
2455                }
2456                if (!do_exit) {
2457                    opline--;
2458                }
2459            } while (!do_exit);
2460            if (call->prev_execute_data) {
2461                /* skip current call region */
2462                level = 0;
2463                do_exit = 0;
2464                do {
2465                    switch (opline->opcode) {
2466                        case ZEND_DO_FCALL:
2467                        case ZEND_DO_ICALL:
2468                        case ZEND_DO_UCALL:
2469                        case ZEND_DO_FCALL_BY_NAME:
2470                            level++;
2471                            break;
2472                        case ZEND_INIT_FCALL:
2473                        case ZEND_INIT_FCALL_BY_NAME:
2474                        case ZEND_INIT_NS_FCALL_BY_NAME:
2475                        case ZEND_INIT_DYNAMIC_CALL:
2476                        case ZEND_INIT_USER_CALL:
2477                        case ZEND_INIT_METHOD_CALL:
2478                        case ZEND_INIT_STATIC_METHOD_CALL:
2479                        case ZEND_NEW:
2480                            if (level == 0) {
2481                                do_exit = 1;
2482                            }
2483                            level--;
2484                            break;
2485                    }
2486                    opline--;
2487                } while (!do_exit);
2488            }
2489
2490            zend_vm_stack_free_args(EX(call));
2491
2492            if (ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS) {
2493                if (ZEND_CALL_INFO(call) & ZEND_CALL_CTOR) {
2494                    if (!(ZEND_CALL_INFO(call) & ZEND_CALL_CTOR_RESULT_UNUSED)) {
2495                        GC_REFCOUNT(Z_OBJ(call->This))--;
2496                    }
2497                    if (GC_REFCOUNT(Z_OBJ(call->This)) == 1) {
2498                        zend_object_store_ctor_failed(Z_OBJ(call->This));
2499                    }
2500                }
2501                OBJ_RELEASE(Z_OBJ(call->This));
2502            }
2503            if (call->func->common.fn_flags & ZEND_ACC_CLOSURE) {
2504                zend_object_release((zend_object *) call->func->common.prototype);
2505            } else if (call->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
2506                zend_string_release(call->func->common.function_name);
2507                zend_free_trampoline(call->func);
2508            }
2509
2510            EX(call) = call->prev_execute_data;
2511            zend_vm_stack_free_call_frame(call);
2512            call = EX(call);
2513        } while (call);
2514    }
2515
2516    for (i = 0; i < EX(func)->op_array.last_brk_cont; i++) {
2517        const zend_brk_cont_element *brk_cont = &EX(func)->op_array.brk_cont_array[i];
2518        if (brk_cont->start < 0) {
2519            continue;
2520        } else if (brk_cont->start > op_num) {
2521            /* further blocks will not be relevant... */
2522            break;
2523        } else if (op_num < brk_cont->brk) {
2524            if (!catch_op_num || catch_op_num >= brk_cont->brk) {
2525                zend_op *brk_opline = &EX(func)->op_array.opcodes[brk_cont->brk];
2526
2527                if (brk_opline->opcode == ZEND_FREE) {
2528                    zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var));
2529                } else if (brk_opline->opcode == ZEND_FE_FREE) {
2530                    zval *var = EX_VAR(brk_opline->op1.var);
2531                    if (Z_TYPE_P(var) != IS_ARRAY && Z_FE_ITER_P(var) != (uint32_t)-1) {
2532                        zend_hash_iterator_del(Z_FE_ITER_P(var));
2533                    }
2534                    zval_ptr_dtor_nogc(var);
2535                } else if (brk_opline->opcode == ZEND_ROPE_END) {
2536                    zend_string **rope = (zend_string **) EX_VAR(brk_opline->op1.var);
2537                    zend_op *last = EX(func)->op_array.opcodes + op_num;
2538                    while ((last->opcode != ZEND_ROPE_ADD && last->opcode != ZEND_ROPE_INIT)
2539                            || last->result.var != brk_opline->op1.var) {
2540                        ZEND_ASSERT(last >= EX(func)->op_array.opcodes);
2541                        last--;
2542                    }
2543                    if (last->opcode == ZEND_ROPE_INIT) {
2544                        zend_string_release(*rope);
2545                    } else {
2546                        int j = last->extended_value;
2547                        do {
2548                            zend_string_release(rope[j]);
2549                        } while (j--);
2550                    }
2551                } else if (brk_opline->opcode == ZEND_END_SILENCE) {
2552                    /* restore previous error_reporting value */
2553                    if (!EG(error_reporting) && Z_LVAL_P(EX_VAR(brk_opline->op1.var)) != 0) {
2554                        EG(error_reporting) = Z_LVAL_P(EX_VAR(brk_opline->op1.var));
2555                    }
2556                }
2557            }
2558        }
2559    }
2560}
2561/* }}} */
2562
2563void zend_cleanup_unfinished_execution(zend_execute_data *execute_data, uint32_t op_num, uint32_t catch_op_num) {
2564    i_cleanup_unfinished_execution(execute_data, op_num, catch_op_num);
2565}
2566
2567#ifdef HAVE_GCC_GLOBAL_REGS
2568# if defined(__GNUC__) && ZEND_GCC_VERSION >= 4008 && defined(i386)
2569#  define ZEND_VM_FP_GLOBAL_REG "%esi"
2570#  define ZEND_VM_IP_GLOBAL_REG "%edi"
2571# elif defined(__GNUC__) && ZEND_GCC_VERSION >= 4008 && defined(__x86_64__)
2572#  define ZEND_VM_FP_GLOBAL_REG "%r14"
2573#  define ZEND_VM_IP_GLOBAL_REG "%r15"
2574# elif defined(__GNUC__) && ZEND_GCC_VERSION >= 4008 && defined(__powerpc64__)
2575#  define ZEND_VM_FP_GLOBAL_REG "r28"
2576#  define ZEND_VM_IP_GLOBAL_REG "r29"
2577# endif
2578#endif
2579
2580#define ZEND_VM_NEXT_OPCODE_EX(check_exception, skip) \
2581    CHECK_SYMBOL_TABLES() \
2582    if (check_exception) { \
2583        OPLINE = EX(opline) + (skip); \
2584    } else { \
2585        OPLINE = opline + (skip); \
2586    } \
2587    ZEND_VM_CONTINUE()
2588
2589#define ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION() \
2590    ZEND_VM_NEXT_OPCODE_EX(1, 1)
2591
2592#define ZEND_VM_NEXT_OPCODE() \
2593    ZEND_VM_NEXT_OPCODE_EX(0, 1)
2594
2595#define ZEND_VM_SET_NEXT_OPCODE(new_op) \
2596    CHECK_SYMBOL_TABLES() \
2597    OPLINE = new_op
2598
2599#define ZEND_VM_SET_OPCODE(new_op) \
2600    CHECK_SYMBOL_TABLES() \
2601    OPLINE = new_op; \
2602    ZEND_VM_INTERRUPT_CHECK()
2603
2604#define ZEND_VM_SET_RELATIVE_OPCODE(opline, offset) \
2605    ZEND_VM_SET_OPCODE(ZEND_OFFSET_TO_OPLINE(opline, offset))
2606
2607#define ZEND_VM_JMP(new_op) \
2608    if (EXPECTED(!EG(exception))) { \
2609        ZEND_VM_SET_OPCODE(new_op); \
2610    } else { \
2611        LOAD_OPLINE(); \
2612    } \
2613    ZEND_VM_CONTINUE()
2614
2615#define ZEND_VM_INC_OPCODE() \
2616    OPLINE++
2617
2618
2619#ifndef VM_SMART_OPCODES
2620# define VM_SMART_OPCODES 1
2621#endif
2622
2623#if VM_SMART_OPCODES
2624# define ZEND_VM_REPEATABLE_OPCODE \
2625    do {
2626# define ZEND_VM_REPEAT_OPCODE(_opcode) \
2627    } while (UNEXPECTED((++opline)->opcode == _opcode)); \
2628    OPLINE = opline; \
2629    ZEND_VM_CONTINUE()
2630# define ZEND_VM_SMART_BRANCH(_result, _check) do { \
2631        int __result; \
2632        if (EXPECTED((opline+1)->opcode == ZEND_JMPZ)) { \
2633            __result = (_result); \
2634        } else if (EXPECTED((opline+1)->opcode == ZEND_JMPNZ)) { \
2635            __result = !(_result); \
2636        } else { \
2637            break; \
2638        } \
2639        if ((_check) && UNEXPECTED(EG(exception))) { \
2640            HANDLE_EXCEPTION(); \
2641        } \
2642        if (__result) { \
2643            ZEND_VM_SET_NEXT_OPCODE(opline + 2); \
2644        } else { \
2645            ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline + 1, (opline+1)->op2)); \
2646        } \
2647        ZEND_VM_CONTINUE(); \
2648    } while (0)
2649#else
2650# define ZEND_VM_REPEATABLE_OPCODE
2651# define ZEND_VM_REPEAT_OPCODE(_opcode)
2652# define ZEND_VM_SMART_BRANCH(_result, _check)
2653#endif
2654
2655#ifdef __GNUC__
2656# define ZEND_VM_GUARD(name) __asm__("#" #name)
2657#else
2658# define ZEND_VM_GUARD(name)
2659#endif
2660
2661#define GET_OP1_UNDEF_CV(ptr, type) \
2662    _get_zval_cv_lookup_ ## type(ptr, opline->op1.var, execute_data)
2663#define GET_OP2_UNDEF_CV(ptr, type) \
2664    _get_zval_cv_lookup_ ## type(ptr, opline->op2.var, execute_data)
2665
2666#include "zend_vm_execute.h"
2667
2668ZEND_API int zend_set_user_opcode_handler(zend_uchar opcode, user_opcode_handler_t handler)
2669{
2670    if (opcode != ZEND_USER_OPCODE) {
2671        if (handler == NULL) {
2672            /* restore the original handler */
2673            zend_user_opcodes[opcode] = opcode;
2674        } else {
2675            zend_user_opcodes[opcode] = ZEND_USER_OPCODE;
2676        }
2677        zend_user_opcode_handlers[opcode] = handler;
2678        return SUCCESS;
2679    }
2680    return FAILURE;
2681}
2682
2683ZEND_API user_opcode_handler_t zend_get_user_opcode_handler(zend_uchar opcode)
2684{
2685    return zend_user_opcode_handlers[opcode];
2686}
2687
2688ZEND_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) {
2689    return get_zval_ptr(op_type, *node, execute_data, should_free, type);
2690}
2691
2692/*
2693 * Local variables:
2694 * tab-width: 4
2695 * c-basic-offset: 4
2696 * indent-tabs-mode: t
2697 * End:
2698 */
2699