root/Zend/zend_execute.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ZEND_FUNCTION
  2. zend_vm_stack_new_page
  3. zend_vm_stack_init
  4. zend_vm_stack_destroy
  5. zend_vm_stack_extend
  6. zend_get_compiled_variable_value
  7. _get_zval_ptr_tmp
  8. _get_zval_ptr_var
  9. _get_zval_ptr_var_deref
  10. zval_undefined_cv
  11. _get_zval_cv_lookup
  12. _get_zval_cv_lookup_BP_VAR_R
  13. _get_zval_cv_lookup_BP_VAR_UNSET
  14. _get_zval_cv_lookup_BP_VAR_RW
  15. _get_zval_cv_lookup_BP_VAR_W
  16. _get_zval_ptr_cv
  17. _get_zval_ptr_cv_undef
  18. _get_zval_ptr_cv_deref
  19. _get_zval_ptr_cv_BP_VAR_R
  20. _get_zval_ptr_cv_deref_BP_VAR_R
  21. _get_zval_ptr_cv_BP_VAR_UNSET
  22. _get_zval_ptr_cv_deref_BP_VAR_UNSET
  23. _get_zval_ptr_cv_BP_VAR_IS
  24. _get_zval_ptr_cv_deref_BP_VAR_IS
  25. _get_zval_ptr_cv_BP_VAR_RW
  26. _get_zval_ptr_cv_deref_BP_VAR_RW
  27. _get_zval_ptr_cv_BP_VAR_W
  28. _get_zval_ptr_cv_undef_BP_VAR_W
  29. _get_zval_ptr_cv_undef_BP_VAR_RW
  30. _get_zval_ptr_cv_deref_BP_VAR_W
  31. _get_zval_ptr
  32. _get_zval_ptr_r
  33. _get_zval_ptr_deref
  34. _get_zval_ptr_r_deref
  35. _get_zval_ptr_undef
  36. _get_zval_ptr_ptr_var
  37. _get_zval_ptr_ptr
  38. _get_obj_zval_ptr_unused
  39. _get_obj_zval_ptr
  40. _get_obj_zval_ptr_undef
  41. _get_obj_zval_ptr_ptr
  42. zend_assign_to_variable_reference
  43. make_real_object
  44. zend_verify_internal_arg_class_kind
  45. zend_verify_arg_class_kind
  46. zend_verify_arg_error
  47. is_null_constant
  48. zend_verify_weak_scalar_type_hint
  49. zend_verify_scalar_type_hint
  50. zend_verify_internal_arg_type
  51. zend_verify_arg_type
  52. zend_verify_missing_arg_type
  53. zend_verify_missing_arg
  54. zend_verify_return_error
  55. zend_verify_internal_return_error
  56. zend_verify_internal_return_type
  57. zend_verify_return_type
  58. zend_verify_missing_return_type
  59. zend_assign_to_object
  60. zend_assign_to_object_dim
  61. zend_binary_assign_op_obj_dim
  62. zend_assign_to_string_offset
  63. zend_post_incdec_overloaded_property
  64. zend_pre_incdec_overloaded_property
  65. zend_assign_op_overloaded_property
  66. zend_extension_statement_handler
  67. zend_extension_fcall_begin_handler
  68. zend_extension_fcall_end_handler
  69. zend_get_target_symbol_table
  70. zend_fetch_dimension_address_inner
  71. zend_check_string_offset
  72. zend_fetch_string_offset
  73. zend_fetch_dimension_address
  74. zend_fetch_dimension_address_W
  75. zend_fetch_dimension_address_RW
  76. zend_fetch_dimension_address_UNSET
  77. zend_fetch_dimension_address_read
  78. zend_fetch_dimension_address_read_R
  79. zend_fetch_dimension_address_read_IS
  80. zend_fetch_dimension_by_zval
  81. zend_fetch_property_address
  82. zend_check_symbol
  83. execute_internal
  84. zend_clean_and_cache_symbol_table
  85. i_free_compiled_variables
  86. zend_free_compiled_variables
  87. i_init_func_execute_data
  88. i_init_code_execute_data
  89. i_init_execute_data
  90. zend_create_generator_execute_data
  91. zend_init_execute_data
  92. zend_is_by_ref_func_arg_fetch
  93. zend_vm_stack_copy_call_frame
  94. zend_vm_stack_extend_call_frame
  95. zend_get_running_generator
  96. cleanup_unfinished_calls
  97. cleanup_live_vars
  98. zend_cleanup_unfinished_execution
  99. zend_set_user_opcode_handler
  100. zend_get_user_opcode_handler
  101. zend_get_zval_ptr
  102. zend_check_internal_arg_type
  103. zend_check_arg_type
  104. zend_check_missing_arg

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

/* [<][>][^][v][top][bottom][index][help] */