root/Zend/zend_execute.c

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

DEFINITIONS

This source file includes following definitions.
  1. zend_pzval_unlock_func
  2. zend_pzval_unlock_free_func
  3. zend_get_compiled_variable_value
  4. _get_zval_ptr_tmp
  5. _get_zval_ptr_var
  6. _get_zval_cv_lookup
  7. _get_zval_cv_lookup_BP_VAR_R
  8. _get_zval_cv_lookup_BP_VAR_UNSET
  9. _get_zval_cv_lookup_BP_VAR_IS
  10. _get_zval_cv_lookup_BP_VAR_RW
  11. _get_zval_cv_lookup_BP_VAR_W
  12. _get_zval_ptr_cv
  13. _get_zval_ptr_cv_BP_VAR_R
  14. _get_zval_ptr_cv_BP_VAR_UNSET
  15. _get_zval_ptr_cv_BP_VAR_IS
  16. _get_zval_ptr_cv_BP_VAR_RW
  17. _get_zval_ptr_cv_BP_VAR_W
  18. _get_zval_ptr
  19. _get_zval_ptr_ptr_var
  20. _get_zval_ptr_ptr_var_fast
  21. _get_zval_ptr_ptr_cv
  22. _get_zval_ptr_ptr_cv_BP_VAR_R
  23. _get_zval_ptr_ptr_cv_BP_VAR_UNSET
  24. _get_zval_ptr_ptr_cv_BP_VAR_IS
  25. _get_zval_ptr_ptr_cv_BP_VAR_RW
  26. _get_zval_ptr_ptr_cv_BP_VAR_W
  27. _get_zval_ptr_ptr
  28. _get_obj_zval_ptr_unused
  29. _get_obj_zval_ptr_ptr
  30. _get_obj_zval_ptr_ptr_unused
  31. _get_obj_zval_ptr
  32. zend_assign_to_variable_reference
  33. make_real_object
  34. zend_verify_arg_class_kind
  35. zend_verify_arg_error
  36. is_null_constant
  37. zend_verify_arg_type
  38. zend_assign_to_object
  39. zend_assign_to_string_offset
  40. zend_assign_tmp_to_variable
  41. zend_assign_const_to_variable
  42. zend_assign_to_variable
  43. zval_deep_copy
  44. zend_extension_statement_handler
  45. zend_extension_fcall_begin_handler
  46. zend_extension_fcall_end_handler
  47. zend_get_target_symbol_table
  48. zend_fetch_dimension_address_inner
  49. zend_fetch_dimension_address
  50. zend_fetch_dimension_address_read
  51. zend_fetch_dimension_by_zval
  52. zend_fetch_property_address
  53. zend_check_symbol
  54. execute_internal
  55. zend_clean_and_cache_symbol_table
  56. i_free_compiled_variables
  57. zend_free_compiled_variables
  58. i_create_execute_data_from_op_array
  59. zend_create_execute_data_from_op_array
  60. zend_is_by_ref_func_arg_fetch
  61. zend_vm_stack_push_args_with_copy
  62. zend_vm_stack_push_args
  63. zend_set_user_opcode_handler
  64. zend_get_user_opcode_handler
  65. zend_get_zval_ptr
  66. zend_get_zval_ptr_ptr

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

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