Back to index

php5  5.3.10
zend_execute.c
Go to the documentation of this file.
00001 /*
00002    +----------------------------------------------------------------------+
00003    | Zend Engine                                                          |
00004    +----------------------------------------------------------------------+
00005    | Copyright (c) 1998-2012 Zend Technologies Ltd. (http://www.zend.com) |
00006    +----------------------------------------------------------------------+
00007    | This source file is subject to version 2.00 of the Zend license,     |
00008    | that is bundled with this package in the file LICENSE, and is        |
00009    | available through the world-wide-web at the following url:           |
00010    | http://www.zend.com/license/2_00.txt.                                |
00011    | If you did not receive a copy of the Zend license and are unable to  |
00012    | obtain it through the world-wide-web, please send a note to          |
00013    | license@zend.com so we can mail you a copy immediately.              |
00014    +----------------------------------------------------------------------+
00015    | Authors: Andi Gutmans <andi@zend.com>                                |
00016    |          Zeev Suraski <zeev@zend.com>                                |
00017    +----------------------------------------------------------------------+
00018 */
00019 
00020 /* $Id: zend_execute.c 321634 2012-01-01 13:15:04Z felipe $ */
00021 
00022 #define ZEND_INTENSIVE_DEBUGGING 0
00023 
00024 #include <stdio.h>
00025 #include <signal.h>
00026 
00027 #include "zend.h"
00028 #include "zend_compile.h"
00029 #include "zend_execute.h"
00030 #include "zend_API.h"
00031 #include "zend_ptr_stack.h"
00032 #include "zend_constants.h"
00033 #include "zend_extensions.h"
00034 #include "zend_ini.h"
00035 #include "zend_exceptions.h"
00036 #include "zend_interfaces.h"
00037 #include "zend_closures.h"
00038 #include "zend_vm.h"
00039 
00040 /* Virtual current working directory support */
00041 #include "tsrm_virtual_cwd.h"
00042 
00043 #define _CONST_CODE  0
00044 #define _TMP_CODE    1
00045 #define _VAR_CODE    2
00046 #define _UNUSED_CODE 3
00047 #define _CV_CODE     4
00048 
00049 typedef int (*incdec_t)(zval *);
00050 
00051 #define get_zval_ptr(node, Ts, should_free, type) _get_zval_ptr(node, Ts, should_free, type TSRMLS_CC)
00052 #define get_zval_ptr_ptr(node, Ts, should_free, type) _get_zval_ptr_ptr(node, Ts, should_free, type TSRMLS_CC)
00053 #define get_obj_zval_ptr(node, Ts, should_free, type) _get_obj_zval_ptr(node, Ts, should_free, type TSRMLS_CC)
00054 #define get_obj_zval_ptr_ptr(node, Ts, should_free, type) _get_obj_zval_ptr_ptr(node, Ts, should_free, type TSRMLS_CC)
00055 
00056 /* Prototypes */
00057 static void zend_extension_statement_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC);
00058 static void zend_extension_fcall_begin_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC);
00059 static void zend_extension_fcall_end_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC);
00060 
00061 #define RETURN_VALUE_USED(opline) (!((opline)->result.u.EA.type & EXT_TYPE_UNUSED))
00062 
00063 #define EX_T(offset) (*(temp_variable *)((char *) EX(Ts) + offset))
00064 #define T(offset) (*(temp_variable *)((char *) Ts + offset))
00065 
00066 #define TEMP_VAR_STACK_LIMIT 2000
00067 
00068 static zend_always_inline void zend_pzval_unlock_func(zval *z, zend_free_op *should_free, int unref TSRMLS_DC)
00069 {
00070        if (!Z_DELREF_P(z)) {
00071               Z_SET_REFCOUNT_P(z, 1);
00072               Z_UNSET_ISREF_P(z);
00073               should_free->var = z;
00074 /*            should_free->is_var = 1; */
00075        } else {
00076               should_free->var = 0;
00077               if (unref && Z_ISREF_P(z) && Z_REFCOUNT_P(z) == 1) {
00078                      Z_UNSET_ISREF_P(z);
00079               }
00080               GC_ZVAL_CHECK_POSSIBLE_ROOT(z);
00081        }
00082 }
00083 
00084 static zend_always_inline void zend_pzval_unlock_free_func(zval *z TSRMLS_DC)
00085 {
00086        if (!Z_DELREF_P(z)) {
00087               if (z != &EG(uninitialized_zval)) {
00088                      GC_REMOVE_ZVAL_FROM_BUFFER(z);
00089                      zval_dtor(z);
00090                      efree(z);
00091               }
00092        }
00093 }
00094 
00095 #define PZVAL_UNLOCK(z, f) zend_pzval_unlock_func(z, f, 1 TSRMLS_CC)
00096 #define PZVAL_UNLOCK_EX(z, f, u) zend_pzval_unlock_func(z, f, u TSRMLS_CC)
00097 #define PZVAL_UNLOCK_FREE(z) zend_pzval_unlock_free_func(z TSRMLS_CC)
00098 #define PZVAL_LOCK(z) Z_ADDREF_P((z))
00099 #define RETURN_VALUE_UNUSED(pzn)   (((pzn)->u.EA.type & EXT_TYPE_UNUSED))
00100 #define SELECTIVE_PZVAL_LOCK(pzv, pzn)    if (!RETURN_VALUE_UNUSED(pzn)) { PZVAL_LOCK(pzv); }
00101 
00102 #define AI_USE_PTR(ai) \
00103        if ((ai).ptr_ptr) { \
00104               (ai).ptr = *((ai).ptr_ptr); \
00105               (ai).ptr_ptr = &((ai).ptr); \
00106        } else { \
00107               (ai).ptr = NULL; \
00108        }
00109 
00110 #define AI_SET_PTR(ai, val)        \
00111        (ai).ptr = (val);                  \
00112        (ai).ptr_ptr = &((ai).ptr);
00113 
00114 #define FREE_OP(should_free) \
00115        if (should_free.var) { \
00116               if ((zend_uintptr_t)should_free.var & 1L) { \
00117                      zval_dtor((zval*)((zend_uintptr_t)should_free.var & ~1L)); \
00118               } else { \
00119                      zval_ptr_dtor(&should_free.var); \
00120               } \
00121        }
00122 
00123 #define FREE_OP_IF_VAR(should_free) \
00124        if (should_free.var != NULL && (((zend_uintptr_t)should_free.var & 1L) == 0)) { \
00125               zval_ptr_dtor(&should_free.var); \
00126        }
00127 
00128 #define FREE_OP_VAR_PTR(should_free) \
00129        if (should_free.var) { \
00130               zval_ptr_dtor(&should_free.var); \
00131        }
00132 
00133 #define TMP_FREE(z) (zval*)(((zend_uintptr_t)(z)) | 1L)
00134 
00135 #define IS_TMP_FREE(should_free) ((zend_uintptr_t)should_free.var & 1L)
00136 
00137 #define INIT_PZVAL_COPY(z,v) \
00138        (z)->value = (v)->value; \
00139        Z_TYPE_P(z) = Z_TYPE_P(v); \
00140        Z_SET_REFCOUNT_P(z, 1); \
00141        Z_UNSET_ISREF_P(z);
00142 
00143 #define MAKE_REAL_ZVAL_PTR(val) \
00144        do { \
00145               zval *_tmp; \
00146               ALLOC_ZVAL(_tmp); \
00147               _tmp->value = (val)->value; \
00148               Z_TYPE_P(_tmp) = Z_TYPE_P(val); \
00149               Z_SET_REFCOUNT_P(_tmp, 1); \
00150               Z_UNSET_ISREF_P(_tmp); \
00151               val = _tmp; \
00152        } while (0)
00153 
00154 /* End of zend_execute_locks.h */
00155 
00156 #define CV_OF(i)     (EG(current_execute_data)->CVs[i])
00157 #define CV_DEF_OF(i) (EG(active_op_array)->vars[i])
00158 
00159 #define CTOR_CALL_BIT    0x1
00160 #define CTOR_USED_BIT    0x2
00161 
00162 #define IS_CTOR_CALL(ce) (((zend_uintptr_t)(ce)) & CTOR_CALL_BIT)
00163 #define IS_CTOR_USED(ce) (((zend_uintptr_t)(ce)) & CTOR_USED_BIT)
00164 
00165 #define ENCODE_CTOR(ce, used) \
00166        ((zend_class_entry*)(((zend_uintptr_t)(ce)) | CTOR_CALL_BIT | ((used) ? CTOR_USED_BIT : 0)))
00167 #define DECODE_CTOR(ce) \
00168        ((zend_class_entry*)(((zend_uintptr_t)(ce)) & ~(CTOR_CALL_BIT|CTOR_USED_BIT)))
00169 
00170 ZEND_API zval** zend_get_compiled_variable_value(const zend_execute_data *execute_data_ptr, zend_uint var)
00171 {
00172        return execute_data_ptr->CVs[var];
00173 }
00174 
00175 static zend_always_inline zval *_get_zval_ptr_tmp(const znode *node, const temp_variable *Ts, zend_free_op *should_free TSRMLS_DC)
00176 {
00177        return should_free->var = &T(node->u.var).tmp_var;
00178 }
00179 
00180 static zval *_get_zval_ptr_var_string_offset(const znode *node, const temp_variable *Ts, zend_free_op *should_free TSRMLS_DC)
00181 {
00182        temp_variable *T = &T(node->u.var);
00183        zval *str = T->str_offset.str;
00184        zval *ptr;
00185 
00186        /* string offset */
00187        ALLOC_ZVAL(ptr);
00188        T->str_offset.ptr = ptr;
00189        should_free->var = ptr;
00190 
00191        if (T->str_offset.str->type != IS_STRING
00192               || ((int)T->str_offset.offset < 0)
00193               || (T->str_offset.str->value.str.len <= (int)T->str_offset.offset)) {
00194               ptr->value.str.val = STR_EMPTY_ALLOC();
00195               ptr->value.str.len = 0;
00196        } else {
00197               ptr->value.str.val = estrndup(str->value.str.val + T->str_offset.offset, 1);
00198               ptr->value.str.len = 1;
00199        }
00200        PZVAL_UNLOCK_FREE(str);
00201        Z_SET_REFCOUNT_P(ptr, 1);
00202        Z_SET_ISREF_P(ptr);
00203        ptr->type = IS_STRING;
00204        return ptr;
00205 }
00206 
00207 static zend_always_inline zval *_get_zval_ptr_var(const znode *node, const temp_variable *Ts, zend_free_op *should_free TSRMLS_DC)
00208 {
00209        zval *ptr = T(node->u.var).var.ptr;
00210        if (EXPECTED(ptr != NULL)) {
00211               PZVAL_UNLOCK(ptr, should_free);
00212               return ptr;
00213        } else {
00214               return _get_zval_ptr_var_string_offset(node, Ts, should_free TSRMLS_CC);
00215        }
00216 }
00217 
00218 static zval **_get_zval_cv_lookup(zval ***ptr, zend_uint var, int type TSRMLS_DC)
00219 {
00220        zend_compiled_variable *cv = &CV_DEF_OF(var);
00221 
00222        if (!EG(active_symbol_table) ||
00223            zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void **)ptr)==FAILURE) {
00224               switch (type) {
00225                      case BP_VAR_R:
00226                      case BP_VAR_UNSET:
00227                             zend_error(E_NOTICE, "Undefined variable: %s", cv->name);
00228                             /* break missing intentionally */
00229                      case BP_VAR_IS:
00230                             return &EG(uninitialized_zval_ptr);
00231                             break;
00232                      case BP_VAR_RW:
00233                             zend_error(E_NOTICE, "Undefined variable: %s", cv->name);
00234                             /* break missing intentionally */
00235                      case BP_VAR_W:
00236                             Z_ADDREF(EG(uninitialized_zval));
00237                             if (!EG(active_symbol_table)) {
00238                                    *ptr = (zval**)EG(current_execute_data)->CVs + (EG(active_op_array)->last_var + var);
00239                                    **ptr = &EG(uninitialized_zval);
00240                             } else {
00241                                    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);
00242                             }
00243                             break;
00244               }
00245        }
00246        return *ptr;
00247 }
00248 
00249 static zend_always_inline zval *_get_zval_ptr_cv(const znode *node, const temp_variable *Ts, int type TSRMLS_DC)
00250 {
00251        zval ***ptr = &CV_OF(node->u.var);
00252 
00253        if (UNEXPECTED(*ptr == NULL)) {
00254               return *_get_zval_cv_lookup(ptr, node->u.var, type TSRMLS_CC);
00255        }
00256        return **ptr;
00257 }
00258 
00259 static inline zval *_get_zval_ptr(znode *node, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC)
00260 {
00261 /*     should_free->is_var = 0; */
00262        switch (node->op_type) {
00263               case IS_CONST:
00264                      should_free->var = 0;
00265                      return &node->u.constant;
00266                      break;
00267               case IS_TMP_VAR:
00268                      should_free->var = TMP_FREE(&T(node->u.var).tmp_var);
00269                      return &T(node->u.var).tmp_var;
00270                      break;
00271               case IS_VAR:
00272                      return _get_zval_ptr_var(node, Ts, should_free TSRMLS_CC);
00273                      break;
00274               case IS_UNUSED:
00275                      should_free->var = 0;
00276                      return NULL;
00277                      break;
00278               case IS_CV:
00279                      should_free->var = 0;
00280                      return _get_zval_ptr_cv(node, Ts, type TSRMLS_CC);
00281                      break;
00282               EMPTY_SWITCH_DEFAULT_CASE()
00283        }
00284        return NULL;
00285 }
00286 
00287 static zend_always_inline zval **_get_zval_ptr_ptr_var(const znode *node, const temp_variable *Ts, zend_free_op *should_free TSRMLS_DC)
00288 {
00289        zval** ptr_ptr = T(node->u.var).var.ptr_ptr;
00290 
00291        if (EXPECTED(ptr_ptr != NULL)) {
00292               PZVAL_UNLOCK(*ptr_ptr, should_free);
00293        } else {
00294               /* string offset */
00295               PZVAL_UNLOCK(T(node->u.var).str_offset.str, should_free);
00296        }
00297        return ptr_ptr;
00298 }
00299 
00300 static zend_always_inline zval **_get_zval_ptr_ptr_cv(const znode *node, const temp_variable *Ts, int type TSRMLS_DC)
00301 {
00302        zval ***ptr = &CV_OF(node->u.var);
00303 
00304        if (UNEXPECTED(*ptr == NULL)) {
00305               return _get_zval_cv_lookup(ptr, node->u.var, type TSRMLS_CC);
00306        }
00307        return *ptr;
00308 }
00309 
00310 static inline zval **_get_zval_ptr_ptr(const znode *node, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC)
00311 {
00312        if (node->op_type == IS_CV) {
00313               should_free->var = 0;
00314               return _get_zval_ptr_ptr_cv(node, Ts, type TSRMLS_CC);
00315        } else if (node->op_type == IS_VAR) {
00316               return _get_zval_ptr_ptr_var(node, Ts, should_free TSRMLS_CC);
00317        } else {
00318               should_free->var = 0;
00319               return NULL;
00320        }
00321 }
00322 
00323 static zend_always_inline zval *_get_obj_zval_ptr_unused(TSRMLS_D)
00324 {
00325        if (EXPECTED(EG(This) != NULL)) {
00326               return EG(This);
00327        } else {
00328               zend_error_noreturn(E_ERROR, "Using $this when not in object context");
00329               return NULL;
00330        }
00331 }
00332 
00333 static inline zval **_get_obj_zval_ptr_ptr(const znode *op, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC)
00334 {
00335        if (op->op_type == IS_UNUSED) {
00336               if (EXPECTED(EG(This) != NULL)) {
00337                      /* this should actually never be modified, _ptr_ptr is modified only when
00338                         the object is empty */
00339                      should_free->var = 0;
00340                      return &EG(This);
00341               } else {
00342                      zend_error_noreturn(E_ERROR, "Using $this when not in object context");
00343               }
00344        }
00345        return get_zval_ptr_ptr(op, Ts, should_free, type);
00346 }
00347 
00348 static zend_always_inline zval **_get_obj_zval_ptr_ptr_unused(TSRMLS_D)
00349 {
00350        if (EXPECTED(EG(This) != NULL)) {
00351               return &EG(This);
00352        } else {
00353               zend_error_noreturn(E_ERROR, "Using $this when not in object context");
00354               return NULL;
00355        }
00356 }
00357 
00358 static inline zval *_get_obj_zval_ptr(znode *op, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC)
00359 {
00360        if (op->op_type == IS_UNUSED) {
00361               if (EXPECTED(EG(This) != NULL)) {
00362                      should_free->var = 0;
00363                      return EG(This);
00364               } else {
00365                      zend_error_noreturn(E_ERROR, "Using $this when not in object context");
00366               }
00367        }
00368        return get_zval_ptr(op, Ts, should_free, type);
00369 }
00370 
00371 static inline void zend_switch_free(temp_variable *T, int extended_value TSRMLS_DC)
00372 {
00373        if (T->var.ptr) {
00374               if (extended_value & ZEND_FE_RESET_VARIABLE) { /* foreach() free */
00375                      Z_DELREF_P(T->var.ptr);
00376               }
00377               zval_ptr_dtor(&T->var.ptr);
00378        } else if (!T->var.ptr_ptr) {
00379               /* perform the equivalent of equivalent of a
00380                * quick & silent get_zval_ptr, and FREE_OP
00381                */
00382               PZVAL_UNLOCK_FREE(T->str_offset.str);
00383        }
00384 }
00385 
00386 static void zend_assign_to_variable_reference(zval **variable_ptr_ptr, zval **value_ptr_ptr TSRMLS_DC)
00387 {
00388        zval *variable_ptr = *variable_ptr_ptr;
00389        zval *value_ptr = *value_ptr_ptr;
00390 
00391        if (variable_ptr == EG(error_zval_ptr) || value_ptr==EG(error_zval_ptr)) {
00392               variable_ptr_ptr = &EG(uninitialized_zval_ptr);
00393        } else if (variable_ptr != value_ptr) {
00394               if (!PZVAL_IS_REF(value_ptr)) {
00395                      /* break it away */
00396                      Z_DELREF_P(value_ptr);
00397                      if (Z_REFCOUNT_P(value_ptr)>0) {
00398                             ALLOC_ZVAL(*value_ptr_ptr);
00399                             **value_ptr_ptr = *value_ptr;
00400                             value_ptr = *value_ptr_ptr;
00401                             zendi_zval_copy_ctor(*value_ptr);
00402                      }
00403                      Z_SET_REFCOUNT_P(value_ptr, 1);
00404                      Z_SET_ISREF_P(value_ptr);
00405               }
00406 
00407               *variable_ptr_ptr = value_ptr;
00408               Z_ADDREF_P(value_ptr);
00409 
00410               zval_ptr_dtor(&variable_ptr);
00411        } else if (!Z_ISREF_P(variable_ptr)) {
00412               if (variable_ptr_ptr == value_ptr_ptr) {
00413                      SEPARATE_ZVAL(variable_ptr_ptr);
00414               } else if (variable_ptr==EG(uninitialized_zval_ptr)
00415                      || Z_REFCOUNT_P(variable_ptr)>2) {
00416                      /* we need to separate */
00417                      Z_SET_REFCOUNT_P(variable_ptr, Z_REFCOUNT_P(variable_ptr) - 2);
00418                      ALLOC_ZVAL(*variable_ptr_ptr);
00419                      **variable_ptr_ptr = *variable_ptr;
00420                      zval_copy_ctor(*variable_ptr_ptr);
00421                      *value_ptr_ptr = *variable_ptr_ptr;
00422                      Z_SET_REFCOUNT_PP(variable_ptr_ptr, 2);
00423               }
00424               Z_SET_ISREF_PP(variable_ptr_ptr);
00425        }
00426 }
00427 
00428 /* this should modify object only if it's empty */
00429 static inline void make_real_object(zval **object_ptr TSRMLS_DC)
00430 {
00431        if (Z_TYPE_PP(object_ptr) == IS_NULL
00432               || (Z_TYPE_PP(object_ptr) == IS_BOOL && Z_LVAL_PP(object_ptr) == 0)
00433               || (Z_TYPE_PP(object_ptr) == IS_STRING && Z_STRLEN_PP(object_ptr) == 0)
00434        ) {
00435               zend_error(E_STRICT, "Creating default object from empty value");
00436 
00437               SEPARATE_ZVAL_IF_NOT_REF(object_ptr);
00438               zval_dtor(*object_ptr);
00439               object_init(*object_ptr);
00440        }
00441 }
00442 
00443 static inline 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)
00444 {
00445        *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);
00446 
00447        *class_name = (*pce) ? (*pce)->name: cur_arg_info->class_name;
00448        if (*pce && (*pce)->ce_flags & ZEND_ACC_INTERFACE) {
00449               return "implement interface ";
00450        } else {
00451               return "be an instance of ";
00452        }
00453 }
00454 
00455 static inline int zend_verify_arg_error(const zend_function *zf, zend_uint arg_num, const zend_arg_info *cur_arg_info, const char *need_msg, const char *need_kind, const char *given_msg, char *given_kind TSRMLS_DC)
00456 {
00457        zend_execute_data *ptr = EG(current_execute_data)->prev_execute_data;
00458        char *fname = zf->common.function_name;
00459        char *fsep;
00460        char *fclass;
00461 
00462        if (zf->common.scope) {
00463               fsep =  "::";
00464               fclass = zf->common.scope->name;
00465        } else {
00466               fsep =  "";
00467               fclass = "";
00468        }
00469 
00470        if (ptr && ptr->op_array) {
00471               zend_error(E_RECOVERABLE_ERROR, "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);
00472        } else {
00473               zend_error(E_RECOVERABLE_ERROR, "Argument %d passed to %s%s%s() must %s%s, %s%s given", arg_num, fclass, fsep, fname, need_msg, need_kind, given_msg, given_kind);
00474        }
00475        return 0;
00476 }
00477 
00478 static inline int zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zval *arg, ulong fetch_type TSRMLS_DC)
00479 {
00480        zend_arg_info *cur_arg_info;
00481        char *need_msg;
00482        zend_class_entry *ce;
00483 
00484        if (!zf->common.arg_info
00485               || arg_num>zf->common.num_args) {
00486               return 1;
00487        }
00488 
00489        cur_arg_info = &zf->common.arg_info[arg_num-1];
00490 
00491        if (cur_arg_info->class_name) {
00492               const char *class_name;
00493 
00494               if (!arg) {
00495                      need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC);
00496                      return zend_verify_arg_error(zf, arg_num, cur_arg_info, need_msg, class_name, "none", "" TSRMLS_CC);
00497               }
00498               if (Z_TYPE_P(arg) == IS_OBJECT) {
00499                      need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC);
00500                      if (!ce || !instanceof_function(Z_OBJCE_P(arg), ce TSRMLS_CC)) {
00501                             return zend_verify_arg_error(zf, arg_num, cur_arg_info, need_msg, class_name, "instance of ", Z_OBJCE_P(arg)->name TSRMLS_CC);
00502                      }
00503               } else if (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null) {
00504                      need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC);
00505                      return zend_verify_arg_error(zf, arg_num, cur_arg_info, need_msg, class_name, zend_zval_type_name(arg), "" TSRMLS_CC);
00506               }
00507        } else if (cur_arg_info->array_type_hint) {
00508               if (!arg) {
00509                      return zend_verify_arg_error(zf, arg_num, cur_arg_info, "be an array", "", "none", "" TSRMLS_CC);
00510               }
00511               if (Z_TYPE_P(arg) != IS_ARRAY && (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null)) {
00512                      return zend_verify_arg_error(zf, arg_num, cur_arg_info, "be an array", "", zend_zval_type_name(arg), "" TSRMLS_CC);
00513               }
00514        }
00515        return 1;
00516 }
00517 
00518 static inline void zend_assign_to_object(znode *result, zval **object_ptr, zval *property_name, znode *value_op, const temp_variable *Ts, int opcode TSRMLS_DC)
00519 
00520 {
00521        zval *object = *object_ptr;
00522        zend_free_op free_value;
00523        zval *value = get_zval_ptr(value_op, Ts, &free_value, BP_VAR_R);
00524        zval **retval = &T(result->u.var).var.ptr;
00525 
00526        if (Z_TYPE_P(object) != IS_OBJECT) {
00527               if (object == EG(error_zval_ptr)) {
00528                      if (!RETURN_VALUE_UNUSED(result)) {
00529                             *retval = EG(uninitialized_zval_ptr);
00530                             PZVAL_LOCK(*retval);
00531                      }
00532                      FREE_OP(free_value);
00533                      return;
00534               }
00535               if (Z_TYPE_P(object) == IS_NULL ||
00536                   (Z_TYPE_P(object) == IS_BOOL && Z_LVAL_P(object) == 0) ||
00537                   (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0)) {
00538                      SEPARATE_ZVAL_IF_NOT_REF(object_ptr);
00539                      object = *object_ptr;
00540                      Z_ADDREF_P(object);
00541                      zend_error(E_STRICT, "Creating default object from empty value");
00542                      if (Z_REFCOUNT_P(object) == 1) {
00543                             /* object was removed by error handler, nothing to assign to */
00544                             zval_ptr_dtor(&object);
00545                             if (retval) {
00546                                    *retval = &EG(uninitialized_zval);
00547                                    PZVAL_LOCK(*retval);
00548                             }
00549                             FREE_OP(free_value);
00550                             return;
00551                      }
00552                      Z_DELREF_P(object);
00553                      zval_dtor(object);
00554                      object_init(object);
00555               } else {
00556                      zend_error(E_WARNING, "Attempt to assign property of non-object");
00557                      if (!RETURN_VALUE_UNUSED(result)) {
00558                             *retval = EG(uninitialized_zval_ptr);
00559                             PZVAL_LOCK(*retval);
00560                      }
00561                      FREE_OP(free_value);
00562                      return;
00563               }
00564        }
00565        
00566        /* separate our value if necessary */
00567        if (value_op->op_type == IS_TMP_VAR) {
00568               zval *orig_value = value;
00569 
00570               ALLOC_ZVAL(value);
00571               *value = *orig_value;
00572               Z_UNSET_ISREF_P(value);
00573               Z_SET_REFCOUNT_P(value, 0);
00574        } else if (value_op->op_type == IS_CONST) {
00575               zval *orig_value = value;
00576 
00577               ALLOC_ZVAL(value);
00578               *value = *orig_value;
00579               Z_UNSET_ISREF_P(value);
00580               Z_SET_REFCOUNT_P(value, 0);
00581               zval_copy_ctor(value);
00582        }
00583 
00584 
00585        Z_ADDREF_P(value);
00586        if (opcode == ZEND_ASSIGN_OBJ) {
00587               if (!Z_OBJ_HT_P(object)->write_property) {
00588                      zend_error(E_WARNING, "Attempt to assign property of non-object");
00589                      if (!RETURN_VALUE_UNUSED(result)) {
00590                             *retval = EG(uninitialized_zval_ptr);
00591                             PZVAL_LOCK(*retval);
00592                      }
00593                      if (value_op->op_type == IS_TMP_VAR) {
00594                             FREE_ZVAL(value);
00595                      } else if (value_op->op_type == IS_CONST) {
00596                             zval_ptr_dtor(&value);
00597                      }
00598                      FREE_OP(free_value);
00599                      return;
00600               }
00601               Z_OBJ_HT_P(object)->write_property(object, property_name, value TSRMLS_CC);
00602        } else {
00603               /* Note:  property_name in this case is really the array index! */
00604               if (!Z_OBJ_HT_P(object)->write_dimension) {
00605                      zend_error_noreturn(E_ERROR, "Cannot use object as array");
00606               }
00607               Z_OBJ_HT_P(object)->write_dimension(object, property_name, value TSRMLS_CC);
00608        }
00609 
00610        if (!RETURN_VALUE_UNUSED(result) && !EG(exception)) {
00611               AI_SET_PTR(T(result->u.var).var, value);
00612               PZVAL_LOCK(value);
00613        }
00614        zval_ptr_dtor(&value);
00615        FREE_OP_IF_VAR(free_value);
00616 }
00617 
00618 static inline int zend_assign_to_string_offset(const temp_variable *T, const zval *value, int value_type TSRMLS_DC)
00619 {
00620        if (Z_TYPE_P(T->str_offset.str) == IS_STRING) {
00621 
00622               if (((int)T->str_offset.offset < 0)) {
00623                      zend_error(E_WARNING, "Illegal string offset:  %d", T->str_offset.offset);
00624                      return 0;
00625               }
00626 
00627               if (T->str_offset.offset >= Z_STRLEN_P(T->str_offset.str)) {
00628                      Z_STRVAL_P(T->str_offset.str) = (char *) erealloc(Z_STRVAL_P(T->str_offset.str), T->str_offset.offset+1+1);
00629                      memset(Z_STRVAL_P(T->str_offset.str) + Z_STRLEN_P(T->str_offset.str),
00630                             ' ',
00631                             T->str_offset.offset - Z_STRLEN_P(T->str_offset.str));
00632                      Z_STRVAL_P(T->str_offset.str)[T->str_offset.offset+1] = 0;
00633                      Z_STRLEN_P(T->str_offset.str) = T->str_offset.offset+1;
00634               }
00635 
00636               if (Z_TYPE_P(value) != IS_STRING) {
00637                      zval tmp = *value;
00638 
00639                      if (value_type != IS_TMP_VAR) {
00640                             zval_copy_ctor(&tmp);
00641                      }
00642                      convert_to_string(&tmp);
00643                      Z_STRVAL_P(T->str_offset.str)[T->str_offset.offset] = Z_STRVAL(tmp)[0];
00644                      STR_FREE(Z_STRVAL(tmp));
00645               } else {
00646                      Z_STRVAL_P(T->str_offset.str)[T->str_offset.offset] = Z_STRVAL_P(value)[0];
00647                      if (value_type == IS_TMP_VAR) {
00648                             /* we can safely free final_value here
00649                              * because separation is done only
00650                              * in case value_type == IS_VAR */
00651                             STR_FREE(Z_STRVAL_P(value));
00652                      }
00653               }
00654               /*
00655                * the value of an assignment to a string offset is undefined
00656               T(result->u.var).var = &T->str_offset.str;
00657               */
00658        }
00659        return 1;
00660 }
00661 
00662 static inline zval* zend_assign_to_variable(zval **variable_ptr_ptr, zval *value, int is_tmp_var TSRMLS_DC)
00663 {
00664        zval *variable_ptr = *variable_ptr_ptr;
00665        zval garbage;
00666 
00667        if (variable_ptr == EG(error_zval_ptr)) {
00668               if (is_tmp_var) {
00669                      zval_dtor(value);
00670               }
00671               return EG(uninitialized_zval_ptr);
00672        }
00673 
00674        if (Z_TYPE_P(variable_ptr) == IS_OBJECT && Z_OBJ_HANDLER_P(variable_ptr, set)) {
00675               Z_OBJ_HANDLER_P(variable_ptr, set)(variable_ptr_ptr, value TSRMLS_CC);
00676               return variable_ptr;
00677        }
00678 
00679        if (PZVAL_IS_REF(variable_ptr)) {
00680               if (variable_ptr!=value) {
00681                      zend_uint refcount = Z_REFCOUNT_P(variable_ptr);
00682 
00683                      garbage = *variable_ptr;
00684                      *variable_ptr = *value;
00685                      Z_SET_REFCOUNT_P(variable_ptr, refcount);
00686                      Z_SET_ISREF_P(variable_ptr);
00687                      if (!is_tmp_var) {
00688                             zendi_zval_copy_ctor(*variable_ptr);
00689                      }
00690                      zendi_zval_dtor(garbage);
00691                      return variable_ptr;
00692               }
00693        } else {
00694               if (Z_DELREF_P(variable_ptr)==0) {
00695                      if (!is_tmp_var) {
00696                             if (variable_ptr==value) {
00697                                    Z_ADDREF_P(variable_ptr);
00698                             } else if (PZVAL_IS_REF(value)) {
00699                                    garbage = *variable_ptr;
00700                                    *variable_ptr = *value;
00701                                    INIT_PZVAL(variable_ptr);
00702                                    zval_copy_ctor(variable_ptr);
00703                                    zendi_zval_dtor(garbage);
00704                                    return variable_ptr;
00705                             } else {
00706                                    Z_ADDREF_P(value);
00707                                    *variable_ptr_ptr = value;
00708                                    if (variable_ptr != &EG(uninitialized_zval)) {
00709                                           GC_REMOVE_ZVAL_FROM_BUFFER(variable_ptr);
00710                                           zval_dtor(variable_ptr);
00711                                           efree(variable_ptr);
00712                                    }
00713                                    return value;
00714                             }
00715                      } else {
00716                             garbage = *variable_ptr;
00717                             *variable_ptr = *value;
00718                             INIT_PZVAL(variable_ptr);
00719                             zendi_zval_dtor(garbage);
00720                             return variable_ptr;
00721                      }
00722               } else { /* we need to split */
00723                      GC_ZVAL_CHECK_POSSIBLE_ROOT(*variable_ptr_ptr);
00724                      if (!is_tmp_var) {
00725                             if (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) {
00726                                    ALLOC_ZVAL(variable_ptr);
00727                                    *variable_ptr_ptr = variable_ptr;
00728                                    *variable_ptr = *value;
00729                                    Z_SET_REFCOUNT_P(variable_ptr, 1);
00730                                    zval_copy_ctor(variable_ptr);
00731                             } else {
00732                                    *variable_ptr_ptr = value;
00733                                    Z_ADDREF_P(value);
00734                             }
00735                      } else {
00736                             ALLOC_ZVAL(*variable_ptr_ptr);
00737                             Z_SET_REFCOUNT_P(value, 1);
00738                             **variable_ptr_ptr = *value;
00739                      }
00740               }
00741               Z_UNSET_ISREF_PP(variable_ptr_ptr);
00742        }
00743 
00744        return *variable_ptr_ptr;
00745 }
00746 
00747 
00748 /* Utility Functions for Extensions */
00749 static void zend_extension_statement_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC)
00750 {
00751        if (extension->statement_handler) {
00752               extension->statement_handler(op_array);
00753        }
00754 }
00755 
00756 
00757 static void zend_extension_fcall_begin_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC)
00758 {
00759        if (extension->fcall_begin_handler) {
00760               extension->fcall_begin_handler(op_array);
00761        }
00762 }
00763 
00764 
00765 static void zend_extension_fcall_end_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC)
00766 {
00767        if (extension->fcall_end_handler) {
00768               extension->fcall_end_handler(op_array);
00769        }
00770 }
00771 
00772 
00773 static inline HashTable *zend_get_target_symbol_table(const zend_op *opline, const temp_variable *Ts, int type, const zval *variable TSRMLS_DC)
00774 {
00775        switch (opline->op2.u.EA.type) {
00776               case ZEND_FETCH_LOCAL:
00777                      if (!EG(active_symbol_table)) {
00778                             zend_rebuild_symbol_table(TSRMLS_C);
00779                      }
00780                      return EG(active_symbol_table);
00781                      break;
00782               case ZEND_FETCH_GLOBAL:
00783               case ZEND_FETCH_GLOBAL_LOCK:
00784                      return &EG(symbol_table);
00785                      break;
00786               case ZEND_FETCH_STATIC:
00787                      if (!EG(active_op_array)->static_variables) {
00788                             ALLOC_HASHTABLE(EG(active_op_array)->static_variables);
00789                             zend_hash_init(EG(active_op_array)->static_variables, 2, NULL, ZVAL_PTR_DTOR, 0);
00790                      }
00791                      return EG(active_op_array)->static_variables;
00792                      break;
00793               EMPTY_SWITCH_DEFAULT_CASE()
00794        }
00795        return NULL;
00796 }
00797 
00798 static inline zval **zend_fetch_dimension_address_inner(HashTable *ht, const zval *dim, int type TSRMLS_DC)
00799 {
00800        zval **retval;
00801        char *offset_key;
00802        int offset_key_length;
00803        long index;
00804 
00805        switch (dim->type) {
00806               case IS_NULL:
00807                      offset_key = "";
00808                      offset_key_length = 0;
00809                      goto fetch_string_dim;
00810 
00811               case IS_STRING:
00812                      
00813                      offset_key = dim->value.str.val;
00814                      offset_key_length = dim->value.str.len;
00815                      
00816 fetch_string_dim:
00817                      if (zend_symtable_find(ht, offset_key, offset_key_length+1, (void **) &retval) == FAILURE) {
00818                             switch (type) {
00819                                    case BP_VAR_R:
00820                                           zend_error(E_NOTICE, "Undefined index: %s", offset_key);
00821                                           /* break missing intentionally */
00822                                    case BP_VAR_UNSET:
00823                                    case BP_VAR_IS:
00824                                           retval = &EG(uninitialized_zval_ptr);
00825                                           break;
00826                                    case BP_VAR_RW:
00827                                           zend_error(E_NOTICE,"Undefined index: %s", offset_key);
00828                                           /* break missing intentionally */
00829                                    case BP_VAR_W: {
00830                                                  zval *new_zval = &EG(uninitialized_zval);
00831 
00832                                                  Z_ADDREF_P(new_zval);
00833                                                  zend_symtable_update(ht, offset_key, offset_key_length+1, &new_zval, sizeof(zval *), (void **) &retval);
00834                                           }
00835                                           break;
00836                             }
00837                      }
00838                      break;
00839               case IS_DOUBLE:
00840                      index = zend_dval_to_lval(Z_DVAL_P(dim));
00841                      goto num_index;
00842               case IS_RESOURCE:
00843                      zend_error(E_STRICT, "Resource ID#%ld used as offset, casting to integer (%ld)", Z_LVAL_P(dim), Z_LVAL_P(dim));
00844                      /* Fall Through */
00845               case IS_BOOL:
00846               case IS_LONG:
00847                      index = Z_LVAL_P(dim);
00848 num_index:
00849                      if (zend_hash_index_find(ht, index, (void **) &retval) == FAILURE) {
00850                             switch (type) {
00851                                    case BP_VAR_R:
00852                                           zend_error(E_NOTICE,"Undefined offset: %ld", index);
00853                                           /* break missing intentionally */
00854                                    case BP_VAR_UNSET:
00855                                    case BP_VAR_IS:
00856                                           retval = &EG(uninitialized_zval_ptr);
00857                                           break;
00858                                    case BP_VAR_RW:
00859                                           zend_error(E_NOTICE,"Undefined offset: %ld", index);
00860                                           /* break missing intentionally */
00861                                    case BP_VAR_W: {
00862                                           zval *new_zval = &EG(uninitialized_zval);
00863 
00864                                           Z_ADDREF_P(new_zval);
00865                                           zend_hash_index_update(ht, index, &new_zval, sizeof(zval *), (void **) &retval);
00866                                    }
00867                                    break;
00868                             }
00869                      }
00870                      break;
00871 
00872               default:
00873                      zend_error(E_WARNING, "Illegal offset type");
00874                      return (type == BP_VAR_W || type == BP_VAR_RW) ?
00875                             &EG(error_zval_ptr) : &EG(uninitialized_zval_ptr);
00876        }
00877        return retval;
00878 }
00879 
00880 static void zend_fetch_dimension_address(temp_variable *result, zval **container_ptr, zval *dim, int dim_is_tmp_var, int type TSRMLS_DC)
00881 {
00882        zval *container = *container_ptr;
00883        zval **retval;
00884 
00885        switch (Z_TYPE_P(container)) {
00886 
00887               case IS_ARRAY:
00888                      if (type != BP_VAR_UNSET && Z_REFCOUNT_P(container)>1 && !PZVAL_IS_REF(container)) {
00889                             SEPARATE_ZVAL(container_ptr);
00890                             container = *container_ptr;
00891                      }
00892 fetch_from_array:
00893                      if (dim == NULL) {
00894                             zval *new_zval = &EG(uninitialized_zval);
00895 
00896                             Z_ADDREF_P(new_zval);
00897                             if (zend_hash_next_index_insert(Z_ARRVAL_P(container), &new_zval, sizeof(zval *), (void **) &retval) == FAILURE) {
00898                                    zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied");
00899                                    retval = &EG(error_zval_ptr);
00900                                    Z_DELREF_P(new_zval);
00901                             }
00902                      } else {
00903                             retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, type TSRMLS_CC);
00904                      }
00905                      result->var.ptr_ptr = retval;
00906                      PZVAL_LOCK(*retval);
00907                      return;
00908                      break;
00909 
00910               case IS_NULL:
00911                      if (container == EG(error_zval_ptr)) {
00912                             result->var.ptr_ptr = &EG(error_zval_ptr);
00913                             PZVAL_LOCK(EG(error_zval_ptr));
00914                      } else if (type != BP_VAR_UNSET) {
00915 convert_to_array:
00916                             if (!PZVAL_IS_REF(container)) {
00917                                    SEPARATE_ZVAL(container_ptr);
00918                                    container = *container_ptr;
00919                             }
00920                             zval_dtor(container);
00921                             array_init(container);
00922                             goto fetch_from_array;
00923                      } else {
00924                             /* for read-mode only */
00925                             result->var.ptr_ptr = &EG(uninitialized_zval_ptr);
00926                             PZVAL_LOCK(EG(uninitialized_zval_ptr));
00927                      }
00928                      return;
00929                      break;
00930 
00931               case IS_STRING: {
00932                             zval tmp;
00933 
00934                             if (type != BP_VAR_UNSET && Z_STRLEN_P(container)==0) {
00935                                    goto convert_to_array;
00936                             }
00937                             if (dim == NULL) {
00938                                    zend_error_noreturn(E_ERROR, "[] operator not supported for strings");
00939                             }
00940 
00941                             if (Z_TYPE_P(dim) != IS_LONG) {
00942                                    switch(Z_TYPE_P(dim)) {
00943                                           /* case IS_LONG: */
00944                                           case IS_STRING:
00945                                           case IS_DOUBLE:
00946                                           case IS_NULL:
00947                                           case IS_BOOL:
00948                                                  /* do nothing */
00949                                                  break;
00950                                           default:
00951                                                  zend_error(E_WARNING, "Illegal offset type");
00952                                                  break;
00953                                    }
00954 
00955                                    tmp = *dim;
00956                                    zval_copy_ctor(&tmp);
00957                                    convert_to_long(&tmp);
00958                                    dim = &tmp;
00959                             }
00960                             if (type != BP_VAR_UNSET) {
00961                                    SEPARATE_ZVAL_IF_NOT_REF(container_ptr);
00962                             }
00963                             container = *container_ptr;
00964                             result->str_offset.str = container;
00965                             PZVAL_LOCK(container);
00966                             result->str_offset.offset = Z_LVAL_P(dim);
00967                             result->var.ptr_ptr = NULL;
00968                             result->var.ptr = NULL;
00969                             return;
00970                      }
00971                      break;
00972 
00973               case IS_OBJECT:
00974                      if (!Z_OBJ_HT_P(container)->read_dimension) {
00975                             zend_error_noreturn(E_ERROR, "Cannot use object as array");
00976                      } else {
00977                             zval *overloaded_result;
00978 
00979                             if (dim_is_tmp_var) {
00980                                    zval *orig = dim;
00981                                    MAKE_REAL_ZVAL_PTR(dim);
00982                                    ZVAL_NULL(orig);
00983                             }
00984                             overloaded_result = Z_OBJ_HT_P(container)->read_dimension(container, dim, type TSRMLS_CC);
00985 
00986                             if (overloaded_result) {
00987                                    if (!Z_ISREF_P(overloaded_result)) {
00988                                           if (Z_REFCOUNT_P(overloaded_result) > 0) {
00989                                                  zval *tmp = overloaded_result;
00990 
00991                                                  ALLOC_ZVAL(overloaded_result);
00992                                                  *overloaded_result = *tmp;
00993                                                  zval_copy_ctor(overloaded_result);
00994                                                  Z_UNSET_ISREF_P(overloaded_result);
00995                                                  Z_SET_REFCOUNT_P(overloaded_result, 0);
00996                                           }
00997                                           if (Z_TYPE_P(overloaded_result) != IS_OBJECT) {
00998                                                  zend_class_entry *ce = Z_OBJCE_P(container);
00999                                                  zend_error(E_NOTICE, "Indirect modification of overloaded element of %s has no effect", ce->name);
01000                                           }
01001                                    }
01002                                    retval = &overloaded_result;
01003                             } else {
01004                                    retval = &EG(error_zval_ptr);
01005                             }
01006                             AI_SET_PTR(result->var, *retval);
01007                             PZVAL_LOCK(*retval);
01008                             if (dim_is_tmp_var) {
01009                                    zval_ptr_dtor(&dim);
01010                             }
01011                      }
01012                      return;
01013                      break;
01014 
01015               case IS_BOOL:
01016                      if (type != BP_VAR_UNSET && Z_LVAL_P(container)==0) {
01017                             goto convert_to_array;
01018                      }
01019                      /* break missing intentionally */
01020 
01021               default:
01022                      if (type == BP_VAR_UNSET) {
01023                             zend_error(E_WARNING, "Cannot unset offset in a non-array variable");
01024                             AI_SET_PTR(result->var, EG(uninitialized_zval_ptr));
01025                             PZVAL_LOCK(EG(uninitialized_zval_ptr));
01026                      } else {
01027                             zend_error(E_WARNING, "Cannot use a scalar value as an array");
01028                             result->var.ptr_ptr = &EG(error_zval_ptr);
01029                             PZVAL_LOCK(EG(error_zval_ptr));
01030                      }
01031                      break;
01032        }
01033 }
01034 
01035 static void zend_fetch_dimension_address_read(temp_variable *result, zval **container_ptr, zval *dim, int dim_is_tmp_var, int type TSRMLS_DC)
01036 {
01037        zval *container = *container_ptr;
01038        zval **retval;
01039 
01040        switch (Z_TYPE_P(container)) {
01041 
01042               case IS_ARRAY:
01043                      retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, type TSRMLS_CC);
01044                      if (result) {
01045                             AI_SET_PTR(result->var, *retval);
01046                             PZVAL_LOCK(*retval);
01047                      }
01048                      return;
01049                      break;
01050 
01051               case IS_NULL:
01052                      if (result) {
01053                             AI_SET_PTR(result->var, EG(uninitialized_zval_ptr));
01054                             PZVAL_LOCK(EG(uninitialized_zval_ptr));
01055                      }
01056                      return;
01057                      break;
01058 
01059               case IS_STRING: {
01060                             zval tmp;
01061 
01062                             if (Z_TYPE_P(dim) != IS_LONG) {
01063                                    switch(Z_TYPE_P(dim)) {
01064                                           /* case IS_LONG: */
01065                                           case IS_STRING:
01066                                           case IS_DOUBLE:
01067                                           case IS_NULL:
01068                                           case IS_BOOL:
01069                                                  /* do nothing */
01070                                                  break;
01071                                           default:
01072                                                  zend_error(E_WARNING, "Illegal offset type");
01073                                                  break;
01074                                    }
01075 
01076                                    tmp = *dim;
01077                                    zval_copy_ctor(&tmp);
01078                                    convert_to_long(&tmp);
01079                                    dim = &tmp;
01080                             }
01081                             if (result) {
01082                                    if ((Z_LVAL_P(dim) < 0 || Z_STRLEN_P(container) <= Z_LVAL_P(dim)) && type != BP_VAR_IS) {
01083                                           zend_error(E_NOTICE, "Uninitialized string offset: %ld", Z_LVAL_P(dim));
01084                                    }
01085                                    result->str_offset.str = container;
01086                                    PZVAL_LOCK(container);
01087                                    result->str_offset.offset = Z_LVAL_P(dim);
01088                                    result->var.ptr_ptr = NULL;
01089                                    result->var.ptr = NULL;
01090                             }
01091                             return;
01092                      }
01093                      break;
01094 
01095               case IS_OBJECT:
01096                      if (!Z_OBJ_HT_P(container)->read_dimension) {
01097                             zend_error_noreturn(E_ERROR, "Cannot use object as array");
01098                      } else {
01099                             zval *overloaded_result;
01100 
01101                             if (dim_is_tmp_var) {
01102                                    zval *orig = dim;
01103                                    MAKE_REAL_ZVAL_PTR(dim);
01104                                    ZVAL_NULL(orig);
01105                             }
01106                             overloaded_result = Z_OBJ_HT_P(container)->read_dimension(container, dim, type TSRMLS_CC);
01107 
01108                             if (overloaded_result) {
01109                                    if (result) {
01110                                           AI_SET_PTR(result->var, overloaded_result);
01111                                           PZVAL_LOCK(overloaded_result);
01112                                    } else if (Z_REFCOUNT_P(overloaded_result) == 0) {
01113                                           /* Destroy unused result from offsetGet() magic method */
01114                                           Z_SET_REFCOUNT_P(overloaded_result, 1);
01115                                           zval_ptr_dtor(&overloaded_result);
01116                                    }
01117                             } else if (result) {
01118                                    AI_SET_PTR(result->var, EG(uninitialized_zval_ptr));
01119                                    PZVAL_LOCK(EG(uninitialized_zval_ptr));
01120                             }
01121                             if (dim_is_tmp_var) {
01122                                    zval_ptr_dtor(&dim);
01123                             }
01124                      }
01125                      return;
01126                      break;
01127 
01128               default:
01129                      if (result) {
01130                             AI_SET_PTR(result->var, EG(uninitialized_zval_ptr));
01131                             PZVAL_LOCK(EG(uninitialized_zval_ptr));
01132                      }
01133                      return;
01134                      break;
01135        }
01136 }
01137 
01138 static void zend_fetch_property_address(temp_variable *result, zval **container_ptr, zval *prop_ptr, int type TSRMLS_DC)
01139 {
01140        zval *container = *container_ptr;;
01141 
01142        if (Z_TYPE_P(container) != IS_OBJECT) {
01143               if (container == EG(error_zval_ptr)) {
01144                      result->var.ptr_ptr = &EG(error_zval_ptr);
01145                      PZVAL_LOCK(*result->var.ptr_ptr);
01146                      return;
01147               }
01148 
01149               /* this should modify object only if it's empty */
01150               if (type != BP_VAR_UNSET &&
01151                   ((Z_TYPE_P(container) == IS_NULL ||
01152                    (Z_TYPE_P(container) == IS_BOOL && Z_LVAL_P(container)==0) ||
01153                    (Z_TYPE_P(container) == IS_STRING && Z_STRLEN_P(container)==0)))) {
01154                      if (!PZVAL_IS_REF(container)) {
01155                             SEPARATE_ZVAL(container_ptr);
01156                             container = *container_ptr;
01157                      }
01158                      object_init(container);
01159               } else {
01160                      zend_error(E_WARNING, "Attempt to modify property of non-object");
01161                      result->var.ptr_ptr = &EG(error_zval_ptr);
01162                      PZVAL_LOCK(EG(error_zval_ptr));
01163                      return;
01164               }
01165        }
01166 
01167        if (Z_OBJ_HT_P(container)->get_property_ptr_ptr) {
01168               zval **ptr_ptr = Z_OBJ_HT_P(container)->get_property_ptr_ptr(container, prop_ptr TSRMLS_CC);
01169               if (NULL == ptr_ptr) {
01170                      zval *ptr;
01171 
01172                      if (Z_OBJ_HT_P(container)->read_property &&
01173                             (ptr = Z_OBJ_HT_P(container)->read_property(container, prop_ptr, type TSRMLS_CC)) != NULL) {
01174                             AI_SET_PTR(result->var, ptr);
01175                             PZVAL_LOCK(ptr);
01176                      } else {
01177                             zend_error_noreturn(E_ERROR, "Cannot access undefined property for object with overloaded property access");
01178                      }
01179               } else {
01180                      result->var.ptr_ptr = ptr_ptr;
01181                      PZVAL_LOCK(*ptr_ptr);
01182               }
01183        } else if (Z_OBJ_HT_P(container)->read_property) {
01184               zval *ptr = Z_OBJ_HT_P(container)->read_property(container, prop_ptr, type TSRMLS_CC);
01185 
01186               AI_SET_PTR(result->var, ptr);
01187               PZVAL_LOCK(ptr);
01188        } else {
01189               zend_error(E_WARNING, "This object doesn't support property references");
01190               result->var.ptr_ptr = &EG(error_zval_ptr);
01191               PZVAL_LOCK(EG(error_zval_ptr));
01192        }
01193 }
01194 
01195 static inline zend_brk_cont_element* zend_brk_cont(const zval *nest_levels_zval, int array_offset, const zend_op_array *op_array, const temp_variable *Ts TSRMLS_DC)
01196 {
01197        zval tmp;
01198        int nest_levels, original_nest_levels;
01199        zend_brk_cont_element *jmp_to;
01200 
01201        if (nest_levels_zval->type != IS_LONG) {
01202               tmp = *nest_levels_zval;
01203               zval_copy_ctor(&tmp);
01204               convert_to_long(&tmp);
01205               nest_levels = tmp.value.lval;
01206        } else {
01207               nest_levels = nest_levels_zval->value.lval;
01208        }
01209        original_nest_levels = nest_levels;
01210        do {
01211               if (array_offset==-1) {
01212                      zend_error_noreturn(E_ERROR, "Cannot break/continue %d level%s", original_nest_levels, (original_nest_levels == 1) ? "" : "s");
01213               }
01214               jmp_to = &op_array->brk_cont_array[array_offset];
01215               if (nest_levels>1) {
01216                      zend_op *brk_opline = &op_array->opcodes[jmp_to->brk];
01217 
01218                      switch (brk_opline->opcode) {
01219                             case ZEND_SWITCH_FREE:
01220                                    if (brk_opline->op1.u.EA.type != EXT_TYPE_FREE_ON_RETURN) {
01221                                           zend_switch_free(&T(brk_opline->op1.u.var), brk_opline->extended_value TSRMLS_CC);
01222                                    }
01223                                    break;
01224                             case ZEND_FREE:
01225                                    if (brk_opline->op1.u.EA.type != EXT_TYPE_FREE_ON_RETURN) {
01226                                           zendi_zval_dtor(T(brk_opline->op1.u.var).tmp_var);
01227                                    }
01228                                    break;
01229                      }
01230               }
01231               array_offset = jmp_to->parent;
01232        } while (--nest_levels > 0);
01233        return jmp_to;
01234 }
01235 
01236 #if ZEND_INTENSIVE_DEBUGGING
01237 
01238 #define CHECK_SYMBOL_TABLES()                                                                                                 \
01239        zend_hash_apply(&EG(symbol_table), (apply_func_t) zend_check_symbol TSRMLS_CC);     \
01240        if (&EG(symbol_table)!=EG(active_symbol_table)) {                                                        \
01241               zend_hash_apply(EG(active_symbol_table), (apply_func_t) zend_check_symbol TSRMLS_CC);      \
01242        }
01243 
01244 static int zend_check_symbol(zval **pz TSRMLS_DC)
01245 {
01246        if (Z_TYPE_PP(pz) > 9) {
01247               fprintf(stderr, "Warning!  %x has invalid type!\n", *pz);
01248 /* See http://support.microsoft.com/kb/190351 */
01249 #ifdef PHP_WIN32
01250               fflush(stderr);
01251 #endif
01252        } else if (Z_TYPE_PP(pz) == IS_ARRAY) {
01253               zend_hash_apply(Z_ARRVAL_PP(pz), (apply_func_t) zend_check_symbol TSRMLS_CC);
01254        } else if (Z_TYPE_PP(pz) == IS_OBJECT) {
01255 
01256               /* OBJ-TBI - doesn't support new object model! */
01257               zend_hash_apply(Z_OBJPROP_PP(pz), (apply_func_t) zend_check_symbol TSRMLS_CC);
01258        }
01259 
01260        return 0;
01261 }
01262 
01263 
01264 #else
01265 #define CHECK_SYMBOL_TABLES()
01266 #endif
01267 
01268 ZEND_API opcode_handler_t *zend_opcode_handlers;
01269 
01270 ZEND_API void execute_internal(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC)
01271 {
01272        zval **return_value_ptr = &(*(temp_variable *)((char *) execute_data_ptr->Ts + execute_data_ptr->opline->result.u.var)).var.ptr;
01273        ((zend_internal_function *) execute_data_ptr->function_state.function)->handler(execute_data_ptr->opline->extended_value, *return_value_ptr, execute_data_ptr->function_state.function->common.return_reference?return_value_ptr:NULL, execute_data_ptr->object, return_value_used TSRMLS_CC);
01274 }
01275 
01276 #define ZEND_VM_NEXT_OPCODE() \
01277        CHECK_SYMBOL_TABLES() \
01278        EX(opline)++; \
01279        ZEND_VM_CONTINUE()
01280 
01281 #define ZEND_VM_SET_OPCODE(new_op) \
01282        CHECK_SYMBOL_TABLES() \
01283        EX(opline) = new_op
01284 
01285 #define ZEND_VM_JMP(new_op) \
01286        CHECK_SYMBOL_TABLES() \
01287        if (EXPECTED(!EG(exception))) { \
01288               EX(opline) = new_op; \
01289        } \
01290        ZEND_VM_CONTINUE()
01291 
01292 #define ZEND_VM_INC_OPCODE() \
01293        EX(opline)++
01294 
01295 #include "zend_vm_execute.h"
01296 
01297 ZEND_API int zend_set_user_opcode_handler(zend_uchar opcode, user_opcode_handler_t handler)
01298 {
01299        if (opcode != ZEND_USER_OPCODE) {
01300               zend_user_opcodes[opcode] = ZEND_USER_OPCODE;
01301               zend_user_opcode_handlers[opcode] = handler;
01302               return SUCCESS;
01303        }
01304        return FAILURE;
01305 }
01306 
01307 ZEND_API user_opcode_handler_t zend_get_user_opcode_handler(zend_uchar opcode)
01308 {
01309        return zend_user_opcode_handlers[opcode];
01310 }
01311 
01312 ZEND_API zval *zend_get_zval_ptr(znode *node, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC) {
01313        return get_zval_ptr(node, Ts, should_free, type);
01314 }
01315 
01316 ZEND_API zval **zend_get_zval_ptr_ptr(const znode *node, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC) {
01317        return get_zval_ptr_ptr(node, Ts, should_free, type);
01318 }
01319 
01320 /*
01321  * Local variables:
01322  * tab-width: 4
01323  * c-basic-offset: 4
01324  * indent-tabs-mode: t
01325  * End:
01326  */