File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / Zend / zend_execute.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 23:47:52 2012 UTC (12 years, 4 months ago) by misho
Branches: php, MAIN
CVS tags: v5_3_10, HEAD
php

    1: /*
    2:    +----------------------------------------------------------------------+
    3:    | Zend Engine                                                          |
    4:    +----------------------------------------------------------------------+
    5:    | Copyright (c) 1998-2012 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: zend_execute.c,v 1.1.1.1 2012/02/21 23:47:52 misho Exp $ */
   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_vm.h"
   39: 
   40: /* Virtual current working directory support */
   41: #include "tsrm_virtual_cwd.h"
   42: 
   43: #define _CONST_CODE  0
   44: #define _TMP_CODE    1
   45: #define _VAR_CODE    2
   46: #define _UNUSED_CODE 3
   47: #define _CV_CODE     4
   48: 
   49: typedef int (*incdec_t)(zval *);
   50: 
   51: #define get_zval_ptr(node, Ts, should_free, type) _get_zval_ptr(node, Ts, should_free, type TSRMLS_CC)
   52: #define get_zval_ptr_ptr(node, Ts, should_free, type) _get_zval_ptr_ptr(node, Ts, should_free, type TSRMLS_CC)
   53: #define get_obj_zval_ptr(node, Ts, should_free, type) _get_obj_zval_ptr(node, Ts, should_free, type TSRMLS_CC)
   54: #define get_obj_zval_ptr_ptr(node, Ts, should_free, type) _get_obj_zval_ptr_ptr(node, Ts, should_free, type TSRMLS_CC)
   55: 
   56: /* Prototypes */
   57: static void zend_extension_statement_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC);
   58: static void zend_extension_fcall_begin_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC);
   59: static void zend_extension_fcall_end_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC);
   60: 
   61: #define RETURN_VALUE_USED(opline) (!((opline)->result.u.EA.type & EXT_TYPE_UNUSED))
   62: 
   63: #define EX_T(offset) (*(temp_variable *)((char *) EX(Ts) + offset))
   64: #define T(offset) (*(temp_variable *)((char *) Ts + offset))
   65: 
   66: #define TEMP_VAR_STACK_LIMIT 2000
   67: 
   68: static zend_always_inline void zend_pzval_unlock_func(zval *z, zend_free_op *should_free, int unref TSRMLS_DC)
   69: {
   70: 	if (!Z_DELREF_P(z)) {
   71: 		Z_SET_REFCOUNT_P(z, 1);
   72: 		Z_UNSET_ISREF_P(z);
   73: 		should_free->var = z;
   74: /*		should_free->is_var = 1; */
   75: 	} else {
   76: 		should_free->var = 0;
   77: 		if (unref && Z_ISREF_P(z) && Z_REFCOUNT_P(z) == 1) {
   78: 			Z_UNSET_ISREF_P(z);
   79: 		}
   80: 		GC_ZVAL_CHECK_POSSIBLE_ROOT(z);
   81: 	}
   82: }
   83: 
   84: static zend_always_inline void zend_pzval_unlock_free_func(zval *z TSRMLS_DC)
   85: {
   86: 	if (!Z_DELREF_P(z)) {
   87: 		if (z != &EG(uninitialized_zval)) {
   88: 			GC_REMOVE_ZVAL_FROM_BUFFER(z);
   89: 			zval_dtor(z);
   90: 			efree(z);
   91: 		}
   92: 	}
   93: }
   94: 
   95: #define PZVAL_UNLOCK(z, f) zend_pzval_unlock_func(z, f, 1 TSRMLS_CC)
   96: #define PZVAL_UNLOCK_EX(z, f, u) zend_pzval_unlock_func(z, f, u TSRMLS_CC)
   97: #define PZVAL_UNLOCK_FREE(z) zend_pzval_unlock_free_func(z TSRMLS_CC)
   98: #define PZVAL_LOCK(z) Z_ADDREF_P((z))
   99: #define RETURN_VALUE_UNUSED(pzn)	(((pzn)->u.EA.type & EXT_TYPE_UNUSED))
  100: #define SELECTIVE_PZVAL_LOCK(pzv, pzn)	if (!RETURN_VALUE_UNUSED(pzn)) { PZVAL_LOCK(pzv); }
  101: 
  102: #define AI_USE_PTR(ai) \
  103: 	if ((ai).ptr_ptr) { \
  104: 		(ai).ptr = *((ai).ptr_ptr); \
  105: 		(ai).ptr_ptr = &((ai).ptr); \
  106: 	} else { \
  107: 		(ai).ptr = NULL; \
  108: 	}
  109: 
  110: #define AI_SET_PTR(ai, val)		\
  111: 	(ai).ptr = (val);			\
  112: 	(ai).ptr_ptr = &((ai).ptr);
  113: 
  114: #define FREE_OP(should_free) \
  115: 	if (should_free.var) { \
  116: 		if ((zend_uintptr_t)should_free.var & 1L) { \
  117: 			zval_dtor((zval*)((zend_uintptr_t)should_free.var & ~1L)); \
  118: 		} else { \
  119: 			zval_ptr_dtor(&should_free.var); \
  120: 		} \
  121: 	}
  122: 
  123: #define FREE_OP_IF_VAR(should_free) \
  124: 	if (should_free.var != NULL && (((zend_uintptr_t)should_free.var & 1L) == 0)) { \
  125: 		zval_ptr_dtor(&should_free.var); \
  126: 	}
  127: 
  128: #define FREE_OP_VAR_PTR(should_free) \
  129: 	if (should_free.var) { \
  130: 		zval_ptr_dtor(&should_free.var); \
  131: 	}
  132: 
  133: #define TMP_FREE(z) (zval*)(((zend_uintptr_t)(z)) | 1L)
  134: 
  135: #define IS_TMP_FREE(should_free) ((zend_uintptr_t)should_free.var & 1L)
  136: 
  137: #define INIT_PZVAL_COPY(z,v) \
  138: 	(z)->value = (v)->value; \
  139: 	Z_TYPE_P(z) = Z_TYPE_P(v); \
  140: 	Z_SET_REFCOUNT_P(z, 1); \
  141: 	Z_UNSET_ISREF_P(z);
  142: 
  143: #define MAKE_REAL_ZVAL_PTR(val) \
  144: 	do { \
  145: 		zval *_tmp; \
  146: 		ALLOC_ZVAL(_tmp); \
  147: 		_tmp->value = (val)->value; \
  148: 		Z_TYPE_P(_tmp) = Z_TYPE_P(val); \
  149: 		Z_SET_REFCOUNT_P(_tmp, 1); \
  150: 		Z_UNSET_ISREF_P(_tmp); \
  151: 		val = _tmp; \
  152: 	} while (0)
  153: 
  154: /* End of zend_execute_locks.h */
  155: 
  156: #define CV_OF(i)     (EG(current_execute_data)->CVs[i])
  157: #define CV_DEF_OF(i) (EG(active_op_array)->vars[i])
  158: 
  159: #define CTOR_CALL_BIT    0x1
  160: #define CTOR_USED_BIT    0x2
  161: 
  162: #define IS_CTOR_CALL(ce) (((zend_uintptr_t)(ce)) & CTOR_CALL_BIT)
  163: #define IS_CTOR_USED(ce) (((zend_uintptr_t)(ce)) & CTOR_USED_BIT)
  164: 
  165: #define ENCODE_CTOR(ce, used) \
  166: 	((zend_class_entry*)(((zend_uintptr_t)(ce)) | CTOR_CALL_BIT | ((used) ? CTOR_USED_BIT : 0)))
  167: #define DECODE_CTOR(ce) \
  168: 	((zend_class_entry*)(((zend_uintptr_t)(ce)) & ~(CTOR_CALL_BIT|CTOR_USED_BIT)))
  169: 
  170: ZEND_API zval** zend_get_compiled_variable_value(const zend_execute_data *execute_data_ptr, zend_uint var)
  171: {
  172: 	return execute_data_ptr->CVs[var];
  173: }
  174: 
  175: static zend_always_inline zval *_get_zval_ptr_tmp(const znode *node, const temp_variable *Ts, zend_free_op *should_free TSRMLS_DC)
  176: {
  177: 	return should_free->var = &T(node->u.var).tmp_var;
  178: }
  179: 
  180: static zval *_get_zval_ptr_var_string_offset(const znode *node, const temp_variable *Ts, zend_free_op *should_free TSRMLS_DC)
  181: {
  182: 	temp_variable *T = &T(node->u.var);
  183: 	zval *str = T->str_offset.str;
  184: 	zval *ptr;
  185: 
  186: 	/* string offset */
  187: 	ALLOC_ZVAL(ptr);
  188: 	T->str_offset.ptr = ptr;
  189: 	should_free->var = ptr;
  190: 
  191: 	if (T->str_offset.str->type != IS_STRING
  192: 		|| ((int)T->str_offset.offset < 0)
  193: 		|| (T->str_offset.str->value.str.len <= (int)T->str_offset.offset)) {
  194: 		ptr->value.str.val = STR_EMPTY_ALLOC();
  195: 		ptr->value.str.len = 0;
  196: 	} else {
  197: 		ptr->value.str.val = estrndup(str->value.str.val + T->str_offset.offset, 1);
  198: 		ptr->value.str.len = 1;
  199: 	}
  200: 	PZVAL_UNLOCK_FREE(str);
  201: 	Z_SET_REFCOUNT_P(ptr, 1);
  202: 	Z_SET_ISREF_P(ptr);
  203: 	ptr->type = IS_STRING;
  204: 	return ptr;
  205: }
  206: 
  207: static zend_always_inline zval *_get_zval_ptr_var(const znode *node, const temp_variable *Ts, zend_free_op *should_free TSRMLS_DC)
  208: {
  209: 	zval *ptr = T(node->u.var).var.ptr;
  210: 	if (EXPECTED(ptr != NULL)) {
  211: 		PZVAL_UNLOCK(ptr, should_free);
  212: 		return ptr;
  213: 	} else {
  214: 		return _get_zval_ptr_var_string_offset(node, Ts, should_free TSRMLS_CC);
  215: 	}
  216: }
  217: 
  218: static zval **_get_zval_cv_lookup(zval ***ptr, zend_uint var, int type 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: 		switch (type) {
  225: 			case BP_VAR_R:
  226: 			case BP_VAR_UNSET:
  227: 				zend_error(E_NOTICE, "Undefined variable: %s", cv->name);
  228: 				/* break missing intentionally */
  229: 			case BP_VAR_IS:
  230: 				return &EG(uninitialized_zval_ptr);
  231: 				break;
  232: 			case BP_VAR_RW:
  233: 				zend_error(E_NOTICE, "Undefined variable: %s", cv->name);
  234: 				/* break missing intentionally */
  235: 			case BP_VAR_W:
  236: 				Z_ADDREF(EG(uninitialized_zval));
  237: 				if (!EG(active_symbol_table)) {
  238: 					*ptr = (zval**)EG(current_execute_data)->CVs + (EG(active_op_array)->last_var + var);
  239: 					**ptr = &EG(uninitialized_zval);
  240: 				} else {
  241: 					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);
  242: 				}
  243: 				break;
  244: 		}
  245: 	}
  246: 	return *ptr;
  247: }
  248: 
  249: static zend_always_inline zval *_get_zval_ptr_cv(const znode *node, const temp_variable *Ts, int type TSRMLS_DC)
  250: {
  251: 	zval ***ptr = &CV_OF(node->u.var);
  252: 
  253: 	if (UNEXPECTED(*ptr == NULL)) {
  254: 		return *_get_zval_cv_lookup(ptr, node->u.var, type TSRMLS_CC);
  255: 	}
  256: 	return **ptr;
  257: }
  258: 
  259: static inline zval *_get_zval_ptr(znode *node, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC)
  260: {
  261: /*	should_free->is_var = 0; */
  262: 	switch (node->op_type) {
  263: 		case IS_CONST:
  264: 			should_free->var = 0;
  265: 			return &node->u.constant;
  266: 			break;
  267: 		case IS_TMP_VAR:
  268: 			should_free->var = TMP_FREE(&T(node->u.var).tmp_var);
  269: 			return &T(node->u.var).tmp_var;
  270: 			break;
  271: 		case IS_VAR:
  272: 			return _get_zval_ptr_var(node, Ts, should_free TSRMLS_CC);
  273: 			break;
  274: 		case IS_UNUSED:
  275: 			should_free->var = 0;
  276: 			return NULL;
  277: 			break;
  278: 		case IS_CV:
  279: 			should_free->var = 0;
  280: 			return _get_zval_ptr_cv(node, Ts, type TSRMLS_CC);
  281: 			break;
  282: 		EMPTY_SWITCH_DEFAULT_CASE()
  283: 	}
  284: 	return NULL;
  285: }
  286: 
  287: static zend_always_inline zval **_get_zval_ptr_ptr_var(const znode *node, const temp_variable *Ts, zend_free_op *should_free TSRMLS_DC)
  288: {
  289: 	zval** ptr_ptr = T(node->u.var).var.ptr_ptr;
  290: 
  291: 	if (EXPECTED(ptr_ptr != NULL)) {
  292: 		PZVAL_UNLOCK(*ptr_ptr, should_free);
  293: 	} else {
  294: 		/* string offset */
  295: 		PZVAL_UNLOCK(T(node->u.var).str_offset.str, should_free);
  296: 	}
  297: 	return ptr_ptr;
  298: }
  299: 
  300: static zend_always_inline zval **_get_zval_ptr_ptr_cv(const znode *node, const temp_variable *Ts, int type TSRMLS_DC)
  301: {
  302: 	zval ***ptr = &CV_OF(node->u.var);
  303: 
  304: 	if (UNEXPECTED(*ptr == NULL)) {
  305: 		return _get_zval_cv_lookup(ptr, node->u.var, type TSRMLS_CC);
  306: 	}
  307: 	return *ptr;
  308: }
  309: 
  310: static inline zval **_get_zval_ptr_ptr(const znode *node, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC)
  311: {
  312: 	if (node->op_type == IS_CV) {
  313: 		should_free->var = 0;
  314: 		return _get_zval_ptr_ptr_cv(node, Ts, type TSRMLS_CC);
  315: 	} else if (node->op_type == IS_VAR) {
  316: 		return _get_zval_ptr_ptr_var(node, Ts, should_free TSRMLS_CC);
  317: 	} else {
  318: 		should_free->var = 0;
  319: 		return NULL;
  320: 	}
  321: }
  322: 
  323: static zend_always_inline zval *_get_obj_zval_ptr_unused(TSRMLS_D)
  324: {
  325: 	if (EXPECTED(EG(This) != NULL)) {
  326: 		return EG(This);
  327: 	} else {
  328: 		zend_error_noreturn(E_ERROR, "Using $this when not in object context");
  329: 		return NULL;
  330: 	}
  331: }
  332: 
  333: static inline zval **_get_obj_zval_ptr_ptr(const znode *op, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC)
  334: {
  335: 	if (op->op_type == IS_UNUSED) {
  336: 		if (EXPECTED(EG(This) != NULL)) {
  337: 			/* this should actually never be modified, _ptr_ptr is modified only when
  338: 			   the object is empty */
  339: 			should_free->var = 0;
  340: 			return &EG(This);
  341: 		} else {
  342: 			zend_error_noreturn(E_ERROR, "Using $this when not in object context");
  343: 		}
  344: 	}
  345: 	return get_zval_ptr_ptr(op, Ts, should_free, type);
  346: }
  347: 
  348: static zend_always_inline zval **_get_obj_zval_ptr_ptr_unused(TSRMLS_D)
  349: {
  350: 	if (EXPECTED(EG(This) != NULL)) {
  351: 		return &EG(This);
  352: 	} else {
  353: 		zend_error_noreturn(E_ERROR, "Using $this when not in object context");
  354: 		return NULL;
  355: 	}
  356: }
  357: 
  358: static inline zval *_get_obj_zval_ptr(znode *op, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC)
  359: {
  360: 	if (op->op_type == IS_UNUSED) {
  361: 		if (EXPECTED(EG(This) != NULL)) {
  362: 			should_free->var = 0;
  363: 			return EG(This);
  364: 		} else {
  365: 			zend_error_noreturn(E_ERROR, "Using $this when not in object context");
  366: 		}
  367: 	}
  368: 	return get_zval_ptr(op, Ts, should_free, type);
  369: }
  370: 
  371: static inline void zend_switch_free(temp_variable *T, int extended_value TSRMLS_DC)
  372: {
  373: 	if (T->var.ptr) {
  374: 		if (extended_value & ZEND_FE_RESET_VARIABLE) { /* foreach() free */
  375: 			Z_DELREF_P(T->var.ptr);
  376: 		}
  377: 		zval_ptr_dtor(&T->var.ptr);
  378: 	} else if (!T->var.ptr_ptr) {
  379: 		/* perform the equivalent of equivalent of a
  380: 		 * quick & silent get_zval_ptr, and FREE_OP
  381: 		 */
  382: 		PZVAL_UNLOCK_FREE(T->str_offset.str);
  383: 	}
  384: }
  385: 
  386: static void zend_assign_to_variable_reference(zval **variable_ptr_ptr, zval **value_ptr_ptr TSRMLS_DC)
  387: {
  388: 	zval *variable_ptr = *variable_ptr_ptr;
  389: 	zval *value_ptr = *value_ptr_ptr;
  390: 
  391: 	if (variable_ptr == EG(error_zval_ptr) || value_ptr==EG(error_zval_ptr)) {
  392: 		variable_ptr_ptr = &EG(uninitialized_zval_ptr);
  393: 	} else if (variable_ptr != value_ptr) {
  394: 		if (!PZVAL_IS_REF(value_ptr)) {
  395: 			/* break it away */
  396: 			Z_DELREF_P(value_ptr);
  397: 			if (Z_REFCOUNT_P(value_ptr)>0) {
  398: 				ALLOC_ZVAL(*value_ptr_ptr);
  399: 				**value_ptr_ptr = *value_ptr;
  400: 				value_ptr = *value_ptr_ptr;
  401: 				zendi_zval_copy_ctor(*value_ptr);
  402: 			}
  403: 			Z_SET_REFCOUNT_P(value_ptr, 1);
  404: 			Z_SET_ISREF_P(value_ptr);
  405: 		}
  406: 
  407: 		*variable_ptr_ptr = value_ptr;
  408: 		Z_ADDREF_P(value_ptr);
  409: 
  410: 		zval_ptr_dtor(&variable_ptr);
  411: 	} else if (!Z_ISREF_P(variable_ptr)) {
  412: 		if (variable_ptr_ptr == value_ptr_ptr) {
  413: 			SEPARATE_ZVAL(variable_ptr_ptr);
  414: 		} else if (variable_ptr==EG(uninitialized_zval_ptr)
  415: 			|| Z_REFCOUNT_P(variable_ptr)>2) {
  416: 			/* we need to separate */
  417: 			Z_SET_REFCOUNT_P(variable_ptr, Z_REFCOUNT_P(variable_ptr) - 2);
  418: 			ALLOC_ZVAL(*variable_ptr_ptr);
  419: 			**variable_ptr_ptr = *variable_ptr;
  420: 			zval_copy_ctor(*variable_ptr_ptr);
  421: 			*value_ptr_ptr = *variable_ptr_ptr;
  422: 			Z_SET_REFCOUNT_PP(variable_ptr_ptr, 2);
  423: 		}
  424: 		Z_SET_ISREF_PP(variable_ptr_ptr);
  425: 	}
  426: }
  427: 
  428: /* this should modify object only if it's empty */
  429: static inline void make_real_object(zval **object_ptr TSRMLS_DC)
  430: {
  431: 	if (Z_TYPE_PP(object_ptr) == IS_NULL
  432: 		|| (Z_TYPE_PP(object_ptr) == IS_BOOL && Z_LVAL_PP(object_ptr) == 0)
  433: 		|| (Z_TYPE_PP(object_ptr) == IS_STRING && Z_STRLEN_PP(object_ptr) == 0)
  434: 	) {
  435: 		zend_error(E_STRICT, "Creating default object from empty value");
  436: 
  437: 		SEPARATE_ZVAL_IF_NOT_REF(object_ptr);
  438: 		zval_dtor(*object_ptr);
  439: 		object_init(*object_ptr);
  440: 	}
  441: }
  442: 
  443: 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)
  444: {
  445: 	*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);
  446: 
  447: 	*class_name = (*pce) ? (*pce)->name: cur_arg_info->class_name;
  448: 	if (*pce && (*pce)->ce_flags & ZEND_ACC_INTERFACE) {
  449: 		return "implement interface ";
  450: 	} else {
  451: 		return "be an instance of ";
  452: 	}
  453: }
  454: 
  455: 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)
  456: {
  457: 	zend_execute_data *ptr = EG(current_execute_data)->prev_execute_data;
  458: 	char *fname = zf->common.function_name;
  459: 	char *fsep;
  460: 	char *fclass;
  461: 
  462: 	if (zf->common.scope) {
  463: 		fsep =  "::";
  464: 		fclass = zf->common.scope->name;
  465: 	} else {
  466: 		fsep =  "";
  467: 		fclass = "";
  468: 	}
  469: 
  470: 	if (ptr && ptr->op_array) {
  471: 		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);
  472: 	} else {
  473: 		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);
  474: 	}
  475: 	return 0;
  476: }
  477: 
  478: static inline int zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zval *arg, ulong fetch_type TSRMLS_DC)
  479: {
  480: 	zend_arg_info *cur_arg_info;
  481: 	char *need_msg;
  482: 	zend_class_entry *ce;
  483: 
  484: 	if (!zf->common.arg_info
  485: 		|| arg_num>zf->common.num_args) {
  486: 		return 1;
  487: 	}
  488: 
  489: 	cur_arg_info = &zf->common.arg_info[arg_num-1];
  490: 
  491: 	if (cur_arg_info->class_name) {
  492: 		const char *class_name;
  493: 
  494: 		if (!arg) {
  495: 			need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC);
  496: 			return zend_verify_arg_error(zf, arg_num, cur_arg_info, need_msg, class_name, "none", "" TSRMLS_CC);
  497: 		}
  498: 		if (Z_TYPE_P(arg) == IS_OBJECT) {
  499: 			need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC);
  500: 			if (!ce || !instanceof_function(Z_OBJCE_P(arg), ce TSRMLS_CC)) {
  501: 				return zend_verify_arg_error(zf, arg_num, cur_arg_info, need_msg, class_name, "instance of ", Z_OBJCE_P(arg)->name TSRMLS_CC);
  502: 			}
  503: 		} else if (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null) {
  504: 			need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC);
  505: 			return zend_verify_arg_error(zf, arg_num, cur_arg_info, need_msg, class_name, zend_zval_type_name(arg), "" TSRMLS_CC);
  506: 		}
  507: 	} else if (cur_arg_info->array_type_hint) {
  508: 		if (!arg) {
  509: 			return zend_verify_arg_error(zf, arg_num, cur_arg_info, "be an array", "", "none", "" TSRMLS_CC);
  510: 		}
  511: 		if (Z_TYPE_P(arg) != IS_ARRAY && (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null)) {
  512: 			return zend_verify_arg_error(zf, arg_num, cur_arg_info, "be an array", "", zend_zval_type_name(arg), "" TSRMLS_CC);
  513: 		}
  514: 	}
  515: 	return 1;
  516: }
  517: 
  518: 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)
  519: 
  520: {
  521: 	zval *object = *object_ptr;
  522: 	zend_free_op free_value;
  523: 	zval *value = get_zval_ptr(value_op, Ts, &free_value, BP_VAR_R);
  524: 	zval **retval = &T(result->u.var).var.ptr;
  525: 
  526: 	if (Z_TYPE_P(object) != IS_OBJECT) {
  527: 		if (object == EG(error_zval_ptr)) {
  528: 			if (!RETURN_VALUE_UNUSED(result)) {
  529: 				*retval = EG(uninitialized_zval_ptr);
  530: 				PZVAL_LOCK(*retval);
  531: 			}
  532: 			FREE_OP(free_value);
  533: 			return;
  534: 		}
  535: 		if (Z_TYPE_P(object) == IS_NULL ||
  536: 		    (Z_TYPE_P(object) == IS_BOOL && Z_LVAL_P(object) == 0) ||
  537: 		    (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0)) {
  538: 			SEPARATE_ZVAL_IF_NOT_REF(object_ptr);
  539: 			object = *object_ptr;
  540: 			Z_ADDREF_P(object);
  541: 			zend_error(E_STRICT, "Creating default object from empty value");
  542: 			if (Z_REFCOUNT_P(object) == 1) {
  543: 				/* object was removed by error handler, nothing to assign to */
  544: 				zval_ptr_dtor(&object);
  545: 				if (retval) {
  546: 					*retval = &EG(uninitialized_zval);
  547: 					PZVAL_LOCK(*retval);
  548: 				}
  549: 				FREE_OP(free_value);
  550: 				return;
  551: 			}
  552: 			Z_DELREF_P(object);
  553: 			zval_dtor(object);
  554: 			object_init(object);
  555: 		} else {
  556: 			zend_error(E_WARNING, "Attempt to assign property of non-object");
  557: 			if (!RETURN_VALUE_UNUSED(result)) {
  558: 				*retval = EG(uninitialized_zval_ptr);
  559: 				PZVAL_LOCK(*retval);
  560: 			}
  561: 			FREE_OP(free_value);
  562: 			return;
  563: 		}
  564: 	}
  565: 	
  566: 	/* separate our value if necessary */
  567: 	if (value_op->op_type == IS_TMP_VAR) {
  568: 		zval *orig_value = value;
  569: 
  570: 		ALLOC_ZVAL(value);
  571: 		*value = *orig_value;
  572: 		Z_UNSET_ISREF_P(value);
  573: 		Z_SET_REFCOUNT_P(value, 0);
  574: 	} else if (value_op->op_type == IS_CONST) {
  575: 		zval *orig_value = value;
  576: 
  577: 		ALLOC_ZVAL(value);
  578: 		*value = *orig_value;
  579: 		Z_UNSET_ISREF_P(value);
  580: 		Z_SET_REFCOUNT_P(value, 0);
  581: 		zval_copy_ctor(value);
  582: 	}
  583: 
  584: 
  585: 	Z_ADDREF_P(value);
  586: 	if (opcode == ZEND_ASSIGN_OBJ) {
  587: 		if (!Z_OBJ_HT_P(object)->write_property) {
  588: 			zend_error(E_WARNING, "Attempt to assign property of non-object");
  589: 			if (!RETURN_VALUE_UNUSED(result)) {
  590: 				*retval = EG(uninitialized_zval_ptr);
  591: 				PZVAL_LOCK(*retval);
  592: 			}
  593: 			if (value_op->op_type == IS_TMP_VAR) {
  594: 				FREE_ZVAL(value);
  595: 			} else if (value_op->op_type == IS_CONST) {
  596: 				zval_ptr_dtor(&value);
  597: 			}
  598: 			FREE_OP(free_value);
  599: 			return;
  600: 		}
  601: 		Z_OBJ_HT_P(object)->write_property(object, property_name, value TSRMLS_CC);
  602: 	} else {
  603: 		/* Note:  property_name in this case is really the array index! */
  604: 		if (!Z_OBJ_HT_P(object)->write_dimension) {
  605: 			zend_error_noreturn(E_ERROR, "Cannot use object as array");
  606: 		}
  607: 		Z_OBJ_HT_P(object)->write_dimension(object, property_name, value TSRMLS_CC);
  608: 	}
  609: 
  610: 	if (!RETURN_VALUE_UNUSED(result) && !EG(exception)) {
  611: 		AI_SET_PTR(T(result->u.var).var, value);
  612: 		PZVAL_LOCK(value);
  613: 	}
  614: 	zval_ptr_dtor(&value);
  615: 	FREE_OP_IF_VAR(free_value);
  616: }
  617: 
  618: static inline int zend_assign_to_string_offset(const temp_variable *T, const zval *value, int value_type TSRMLS_DC)
  619: {
  620: 	if (Z_TYPE_P(T->str_offset.str) == IS_STRING) {
  621: 
  622: 		if (((int)T->str_offset.offset < 0)) {
  623: 			zend_error(E_WARNING, "Illegal string offset:  %d", T->str_offset.offset);
  624: 			return 0;
  625: 		}
  626: 
  627: 		if (T->str_offset.offset >= Z_STRLEN_P(T->str_offset.str)) {
  628: 			Z_STRVAL_P(T->str_offset.str) = (char *) erealloc(Z_STRVAL_P(T->str_offset.str), T->str_offset.offset+1+1);
  629: 			memset(Z_STRVAL_P(T->str_offset.str) + Z_STRLEN_P(T->str_offset.str),
  630: 			       ' ',
  631: 			       T->str_offset.offset - Z_STRLEN_P(T->str_offset.str));
  632: 			Z_STRVAL_P(T->str_offset.str)[T->str_offset.offset+1] = 0;
  633: 			Z_STRLEN_P(T->str_offset.str) = T->str_offset.offset+1;
  634: 		}
  635: 
  636: 		if (Z_TYPE_P(value) != IS_STRING) {
  637: 			zval tmp = *value;
  638: 
  639: 			if (value_type != IS_TMP_VAR) {
  640: 				zval_copy_ctor(&tmp);
  641: 			}
  642: 			convert_to_string(&tmp);
  643: 			Z_STRVAL_P(T->str_offset.str)[T->str_offset.offset] = Z_STRVAL(tmp)[0];
  644: 			STR_FREE(Z_STRVAL(tmp));
  645: 		} else {
  646: 			Z_STRVAL_P(T->str_offset.str)[T->str_offset.offset] = Z_STRVAL_P(value)[0];
  647: 			if (value_type == IS_TMP_VAR) {
  648: 				/* we can safely free final_value here
  649: 				 * because separation is done only
  650: 				 * in case value_type == IS_VAR */
  651: 				STR_FREE(Z_STRVAL_P(value));
  652: 			}
  653: 		}
  654: 		/*
  655: 		 * the value of an assignment to a string offset is undefined
  656: 		T(result->u.var).var = &T->str_offset.str;
  657: 		*/
  658: 	}
  659: 	return 1;
  660: }
  661: 
  662: static inline zval* zend_assign_to_variable(zval **variable_ptr_ptr, zval *value, int is_tmp_var TSRMLS_DC)
  663: {
  664: 	zval *variable_ptr = *variable_ptr_ptr;
  665: 	zval garbage;
  666: 
  667: 	if (variable_ptr == EG(error_zval_ptr)) {
  668: 		if (is_tmp_var) {
  669: 			zval_dtor(value);
  670: 		}
  671: 		return EG(uninitialized_zval_ptr);
  672: 	}
  673: 
  674: 	if (Z_TYPE_P(variable_ptr) == IS_OBJECT && Z_OBJ_HANDLER_P(variable_ptr, set)) {
  675: 		Z_OBJ_HANDLER_P(variable_ptr, set)(variable_ptr_ptr, value TSRMLS_CC);
  676: 		return variable_ptr;
  677: 	}
  678: 
  679:  	if (PZVAL_IS_REF(variable_ptr)) {
  680: 		if (variable_ptr!=value) {
  681: 			zend_uint refcount = Z_REFCOUNT_P(variable_ptr);
  682: 
  683: 			garbage = *variable_ptr;
  684: 			*variable_ptr = *value;
  685: 			Z_SET_REFCOUNT_P(variable_ptr, refcount);
  686: 			Z_SET_ISREF_P(variable_ptr);
  687: 			if (!is_tmp_var) {
  688: 				zendi_zval_copy_ctor(*variable_ptr);
  689: 			}
  690: 			zendi_zval_dtor(garbage);
  691: 			return variable_ptr;
  692: 		}
  693: 	} else {
  694: 		if (Z_DELREF_P(variable_ptr)==0) {
  695: 			if (!is_tmp_var) {
  696: 				if (variable_ptr==value) {
  697: 					Z_ADDREF_P(variable_ptr);
  698: 				} else if (PZVAL_IS_REF(value)) {
  699: 					garbage = *variable_ptr;
  700: 					*variable_ptr = *value;
  701: 					INIT_PZVAL(variable_ptr);
  702: 					zval_copy_ctor(variable_ptr);
  703: 					zendi_zval_dtor(garbage);
  704: 					return variable_ptr;
  705: 				} else {
  706: 					Z_ADDREF_P(value);
  707: 					*variable_ptr_ptr = value;
  708: 					if (variable_ptr != &EG(uninitialized_zval)) {
  709: 						GC_REMOVE_ZVAL_FROM_BUFFER(variable_ptr);
  710: 						zval_dtor(variable_ptr);
  711: 						efree(variable_ptr);
  712: 					}
  713: 					return value;
  714: 				}
  715: 			} else {
  716: 				garbage = *variable_ptr;
  717: 				*variable_ptr = *value;
  718: 				INIT_PZVAL(variable_ptr);
  719: 				zendi_zval_dtor(garbage);
  720: 				return variable_ptr;
  721: 			}
  722: 		} else { /* we need to split */
  723: 			GC_ZVAL_CHECK_POSSIBLE_ROOT(*variable_ptr_ptr);
  724: 			if (!is_tmp_var) {
  725: 				if (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) {
  726: 					ALLOC_ZVAL(variable_ptr);
  727: 					*variable_ptr_ptr = variable_ptr;
  728: 					*variable_ptr = *value;
  729: 					Z_SET_REFCOUNT_P(variable_ptr, 1);
  730: 					zval_copy_ctor(variable_ptr);
  731: 				} else {
  732: 					*variable_ptr_ptr = value;
  733: 					Z_ADDREF_P(value);
  734: 				}
  735: 			} else {
  736: 				ALLOC_ZVAL(*variable_ptr_ptr);
  737: 				Z_SET_REFCOUNT_P(value, 1);
  738: 				**variable_ptr_ptr = *value;
  739: 			}
  740: 		}
  741: 		Z_UNSET_ISREF_PP(variable_ptr_ptr);
  742: 	}
  743: 
  744: 	return *variable_ptr_ptr;
  745: }
  746: 
  747: 
  748: /* Utility Functions for Extensions */
  749: static void zend_extension_statement_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC)
  750: {
  751: 	if (extension->statement_handler) {
  752: 		extension->statement_handler(op_array);
  753: 	}
  754: }
  755: 
  756: 
  757: static void zend_extension_fcall_begin_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC)
  758: {
  759: 	if (extension->fcall_begin_handler) {
  760: 		extension->fcall_begin_handler(op_array);
  761: 	}
  762: }
  763: 
  764: 
  765: static void zend_extension_fcall_end_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC)
  766: {
  767: 	if (extension->fcall_end_handler) {
  768: 		extension->fcall_end_handler(op_array);
  769: 	}
  770: }
  771: 
  772: 
  773: static inline HashTable *zend_get_target_symbol_table(const zend_op *opline, const temp_variable *Ts, int type, const zval *variable TSRMLS_DC)
  774: {
  775: 	switch (opline->op2.u.EA.type) {
  776: 		case ZEND_FETCH_LOCAL:
  777: 			if (!EG(active_symbol_table)) {
  778: 				zend_rebuild_symbol_table(TSRMLS_C);
  779: 			}
  780: 			return EG(active_symbol_table);
  781: 			break;
  782: 		case ZEND_FETCH_GLOBAL:
  783: 		case ZEND_FETCH_GLOBAL_LOCK:
  784: 			return &EG(symbol_table);
  785: 			break;
  786: 		case ZEND_FETCH_STATIC:
  787: 			if (!EG(active_op_array)->static_variables) {
  788: 				ALLOC_HASHTABLE(EG(active_op_array)->static_variables);
  789: 				zend_hash_init(EG(active_op_array)->static_variables, 2, NULL, ZVAL_PTR_DTOR, 0);
  790: 			}
  791: 			return EG(active_op_array)->static_variables;
  792: 			break;
  793: 		EMPTY_SWITCH_DEFAULT_CASE()
  794: 	}
  795: 	return NULL;
  796: }
  797: 
  798: static inline zval **zend_fetch_dimension_address_inner(HashTable *ht, const zval *dim, int type TSRMLS_DC)
  799: {
  800: 	zval **retval;
  801: 	char *offset_key;
  802: 	int offset_key_length;
  803: 	long index;
  804: 
  805: 	switch (dim->type) {
  806: 		case IS_NULL:
  807: 			offset_key = "";
  808: 			offset_key_length = 0;
  809: 			goto fetch_string_dim;
  810: 
  811: 		case IS_STRING:
  812: 			
  813: 			offset_key = dim->value.str.val;
  814: 			offset_key_length = dim->value.str.len;
  815: 			
  816: fetch_string_dim:
  817: 			if (zend_symtable_find(ht, offset_key, offset_key_length+1, (void **) &retval) == FAILURE) {
  818: 				switch (type) {
  819: 					case BP_VAR_R:
  820: 						zend_error(E_NOTICE, "Undefined index: %s", offset_key);
  821: 						/* break missing intentionally */
  822: 					case BP_VAR_UNSET:
  823: 					case BP_VAR_IS:
  824: 						retval = &EG(uninitialized_zval_ptr);
  825: 						break;
  826: 					case BP_VAR_RW:
  827: 						zend_error(E_NOTICE,"Undefined index: %s", offset_key);
  828: 						/* break missing intentionally */
  829: 					case BP_VAR_W: {
  830: 							zval *new_zval = &EG(uninitialized_zval);
  831: 
  832: 							Z_ADDREF_P(new_zval);
  833: 							zend_symtable_update(ht, offset_key, offset_key_length+1, &new_zval, sizeof(zval *), (void **) &retval);
  834: 						}
  835: 						break;
  836: 				}
  837: 			}
  838: 			break;
  839: 		case IS_DOUBLE:
  840: 			index = zend_dval_to_lval(Z_DVAL_P(dim));
  841: 			goto num_index;
  842: 		case IS_RESOURCE:
  843: 			zend_error(E_STRICT, "Resource ID#%ld used as offset, casting to integer (%ld)", Z_LVAL_P(dim), Z_LVAL_P(dim));
  844: 			/* Fall Through */
  845: 		case IS_BOOL:
  846: 		case IS_LONG:
  847: 			index = Z_LVAL_P(dim);
  848: num_index:
  849: 			if (zend_hash_index_find(ht, index, (void **) &retval) == FAILURE) {
  850: 				switch (type) {
  851: 					case BP_VAR_R:
  852: 						zend_error(E_NOTICE,"Undefined offset: %ld", index);
  853: 						/* break missing intentionally */
  854: 					case BP_VAR_UNSET:
  855: 					case BP_VAR_IS:
  856: 						retval = &EG(uninitialized_zval_ptr);
  857: 						break;
  858: 					case BP_VAR_RW:
  859: 						zend_error(E_NOTICE,"Undefined offset: %ld", index);
  860: 						/* break missing intentionally */
  861: 					case BP_VAR_W: {
  862: 						zval *new_zval = &EG(uninitialized_zval);
  863: 
  864: 						Z_ADDREF_P(new_zval);
  865: 						zend_hash_index_update(ht, index, &new_zval, sizeof(zval *), (void **) &retval);
  866: 					}
  867: 					break;
  868: 				}
  869: 			}
  870: 			break;
  871: 
  872: 		default:
  873: 			zend_error(E_WARNING, "Illegal offset type");
  874: 			return (type == BP_VAR_W || type == BP_VAR_RW) ?
  875: 				&EG(error_zval_ptr) : &EG(uninitialized_zval_ptr);
  876: 	}
  877: 	return retval;
  878: }
  879: 
  880: static void zend_fetch_dimension_address(temp_variable *result, zval **container_ptr, zval *dim, int dim_is_tmp_var, int type TSRMLS_DC)
  881: {
  882: 	zval *container = *container_ptr;
  883: 	zval **retval;
  884: 
  885: 	switch (Z_TYPE_P(container)) {
  886: 
  887: 		case IS_ARRAY:
  888: 			if (type != BP_VAR_UNSET && Z_REFCOUNT_P(container)>1 && !PZVAL_IS_REF(container)) {
  889: 				SEPARATE_ZVAL(container_ptr);
  890: 				container = *container_ptr;
  891: 			}
  892: fetch_from_array:
  893: 			if (dim == NULL) {
  894: 				zval *new_zval = &EG(uninitialized_zval);
  895: 
  896: 				Z_ADDREF_P(new_zval);
  897: 				if (zend_hash_next_index_insert(Z_ARRVAL_P(container), &new_zval, sizeof(zval *), (void **) &retval) == FAILURE) {
  898: 					zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied");
  899: 					retval = &EG(error_zval_ptr);
  900: 					Z_DELREF_P(new_zval);
  901: 				}
  902: 			} else {
  903: 				retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, type TSRMLS_CC);
  904: 			}
  905: 			result->var.ptr_ptr = retval;
  906: 			PZVAL_LOCK(*retval);
  907: 			return;
  908: 			break;
  909: 
  910: 		case IS_NULL:
  911: 			if (container == EG(error_zval_ptr)) {
  912: 				result->var.ptr_ptr = &EG(error_zval_ptr);
  913: 				PZVAL_LOCK(EG(error_zval_ptr));
  914: 			} else if (type != BP_VAR_UNSET) {
  915: convert_to_array:
  916: 				if (!PZVAL_IS_REF(container)) {
  917: 					SEPARATE_ZVAL(container_ptr);
  918: 					container = *container_ptr;
  919: 				}
  920: 				zval_dtor(container);
  921: 				array_init(container);
  922: 				goto fetch_from_array;
  923: 			} else {
  924: 				/* for read-mode only */
  925: 				result->var.ptr_ptr = &EG(uninitialized_zval_ptr);
  926: 				PZVAL_LOCK(EG(uninitialized_zval_ptr));
  927: 			}
  928: 			return;
  929: 			break;
  930: 
  931: 		case IS_STRING: {
  932: 				zval tmp;
  933: 
  934: 				if (type != BP_VAR_UNSET && Z_STRLEN_P(container)==0) {
  935: 					goto convert_to_array;
  936: 				}
  937: 				if (dim == NULL) {
  938: 					zend_error_noreturn(E_ERROR, "[] operator not supported for strings");
  939: 				}
  940: 
  941: 				if (Z_TYPE_P(dim) != IS_LONG) {
  942: 					switch(Z_TYPE_P(dim)) {
  943: 						/* case IS_LONG: */
  944: 						case IS_STRING:
  945: 						case IS_DOUBLE:
  946: 						case IS_NULL:
  947: 						case IS_BOOL:
  948: 							/* do nothing */
  949: 							break;
  950: 						default:
  951: 							zend_error(E_WARNING, "Illegal offset type");
  952: 							break;
  953: 					}
  954: 
  955: 					tmp = *dim;
  956: 					zval_copy_ctor(&tmp);
  957: 					convert_to_long(&tmp);
  958: 					dim = &tmp;
  959: 				}
  960: 				if (type != BP_VAR_UNSET) {
  961: 					SEPARATE_ZVAL_IF_NOT_REF(container_ptr);
  962: 				}
  963: 				container = *container_ptr;
  964: 				result->str_offset.str = container;
  965: 				PZVAL_LOCK(container);
  966: 				result->str_offset.offset = Z_LVAL_P(dim);
  967: 				result->var.ptr_ptr = NULL;
  968: 				result->var.ptr = NULL;
  969: 				return;
  970: 			}
  971: 			break;
  972: 
  973: 		case IS_OBJECT:
  974: 			if (!Z_OBJ_HT_P(container)->read_dimension) {
  975: 				zend_error_noreturn(E_ERROR, "Cannot use object as array");
  976: 			} else {
  977: 				zval *overloaded_result;
  978: 
  979: 				if (dim_is_tmp_var) {
  980: 					zval *orig = dim;
  981: 					MAKE_REAL_ZVAL_PTR(dim);
  982: 					ZVAL_NULL(orig);
  983: 				}
  984: 				overloaded_result = Z_OBJ_HT_P(container)->read_dimension(container, dim, type TSRMLS_CC);
  985: 
  986: 				if (overloaded_result) {
  987: 					if (!Z_ISREF_P(overloaded_result)) {
  988: 						if (Z_REFCOUNT_P(overloaded_result) > 0) {
  989: 							zval *tmp = overloaded_result;
  990: 
  991: 							ALLOC_ZVAL(overloaded_result);
  992: 							*overloaded_result = *tmp;
  993: 							zval_copy_ctor(overloaded_result);
  994: 							Z_UNSET_ISREF_P(overloaded_result);
  995: 							Z_SET_REFCOUNT_P(overloaded_result, 0);
  996: 						}
  997: 						if (Z_TYPE_P(overloaded_result) != IS_OBJECT) {
  998: 							zend_class_entry *ce = Z_OBJCE_P(container);
  999: 							zend_error(E_NOTICE, "Indirect modification of overloaded element of %s has no effect", ce->name);
 1000: 						}
 1001: 					}
 1002: 					retval = &overloaded_result;
 1003: 				} else {
 1004: 					retval = &EG(error_zval_ptr);
 1005: 				}
 1006: 				AI_SET_PTR(result->var, *retval);
 1007: 				PZVAL_LOCK(*retval);
 1008: 				if (dim_is_tmp_var) {
 1009: 					zval_ptr_dtor(&dim);
 1010: 				}
 1011: 			}
 1012: 			return;
 1013: 			break;
 1014: 
 1015: 		case IS_BOOL:
 1016: 			if (type != BP_VAR_UNSET && Z_LVAL_P(container)==0) {
 1017: 				goto convert_to_array;
 1018: 			}
 1019: 			/* break missing intentionally */
 1020: 
 1021: 		default:
 1022: 			if (type == BP_VAR_UNSET) {
 1023: 				zend_error(E_WARNING, "Cannot unset offset in a non-array variable");
 1024: 				AI_SET_PTR(result->var, EG(uninitialized_zval_ptr));
 1025: 				PZVAL_LOCK(EG(uninitialized_zval_ptr));
 1026: 			} else {
 1027: 				zend_error(E_WARNING, "Cannot use a scalar value as an array");
 1028: 				result->var.ptr_ptr = &EG(error_zval_ptr);
 1029: 				PZVAL_LOCK(EG(error_zval_ptr));
 1030: 			}
 1031: 			break;
 1032: 	}
 1033: }
 1034: 
 1035: static void zend_fetch_dimension_address_read(temp_variable *result, zval **container_ptr, zval *dim, int dim_is_tmp_var, int type TSRMLS_DC)
 1036: {
 1037: 	zval *container = *container_ptr;
 1038: 	zval **retval;
 1039: 
 1040: 	switch (Z_TYPE_P(container)) {
 1041: 
 1042: 		case IS_ARRAY:
 1043: 			retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, type TSRMLS_CC);
 1044: 			if (result) {
 1045: 				AI_SET_PTR(result->var, *retval);
 1046: 				PZVAL_LOCK(*retval);
 1047: 			}
 1048: 			return;
 1049: 			break;
 1050: 
 1051: 		case IS_NULL:
 1052: 			if (result) {
 1053: 				AI_SET_PTR(result->var, EG(uninitialized_zval_ptr));
 1054: 				PZVAL_LOCK(EG(uninitialized_zval_ptr));
 1055: 			}
 1056: 			return;
 1057: 			break;
 1058: 
 1059: 		case IS_STRING: {
 1060: 				zval tmp;
 1061: 
 1062: 				if (Z_TYPE_P(dim) != IS_LONG) {
 1063: 					switch(Z_TYPE_P(dim)) {
 1064: 						/* case IS_LONG: */
 1065: 						case IS_STRING:
 1066: 						case IS_DOUBLE:
 1067: 						case IS_NULL:
 1068: 						case IS_BOOL:
 1069: 							/* do nothing */
 1070: 							break;
 1071: 						default:
 1072: 							zend_error(E_WARNING, "Illegal offset type");
 1073: 							break;
 1074: 					}
 1075: 
 1076: 					tmp = *dim;
 1077: 					zval_copy_ctor(&tmp);
 1078: 					convert_to_long(&tmp);
 1079: 					dim = &tmp;
 1080: 				}
 1081: 				if (result) {
 1082: 					if ((Z_LVAL_P(dim) < 0 || Z_STRLEN_P(container) <= Z_LVAL_P(dim)) && type != BP_VAR_IS) {
 1083: 						zend_error(E_NOTICE, "Uninitialized string offset: %ld", Z_LVAL_P(dim));
 1084: 					}
 1085: 					result->str_offset.str = container;
 1086: 					PZVAL_LOCK(container);
 1087: 					result->str_offset.offset = Z_LVAL_P(dim);
 1088: 					result->var.ptr_ptr = NULL;
 1089: 					result->var.ptr = NULL;
 1090: 				}
 1091: 				return;
 1092: 			}
 1093: 			break;
 1094: 
 1095: 		case IS_OBJECT:
 1096: 			if (!Z_OBJ_HT_P(container)->read_dimension) {
 1097: 				zend_error_noreturn(E_ERROR, "Cannot use object as array");
 1098: 			} else {
 1099: 				zval *overloaded_result;
 1100: 
 1101: 				if (dim_is_tmp_var) {
 1102: 					zval *orig = dim;
 1103: 					MAKE_REAL_ZVAL_PTR(dim);
 1104: 					ZVAL_NULL(orig);
 1105: 				}
 1106: 				overloaded_result = Z_OBJ_HT_P(container)->read_dimension(container, dim, type TSRMLS_CC);
 1107: 
 1108: 				if (overloaded_result) {
 1109: 					if (result) {
 1110: 						AI_SET_PTR(result->var, overloaded_result);
 1111: 						PZVAL_LOCK(overloaded_result);
 1112: 					} else if (Z_REFCOUNT_P(overloaded_result) == 0) {
 1113: 						/* Destroy unused result from offsetGet() magic method */
 1114: 						Z_SET_REFCOUNT_P(overloaded_result, 1);
 1115: 						zval_ptr_dtor(&overloaded_result);
 1116: 					}
 1117: 				} else if (result) {
 1118: 					AI_SET_PTR(result->var, EG(uninitialized_zval_ptr));
 1119: 					PZVAL_LOCK(EG(uninitialized_zval_ptr));
 1120: 				}
 1121: 				if (dim_is_tmp_var) {
 1122: 					zval_ptr_dtor(&dim);
 1123: 				}
 1124: 			}
 1125: 			return;
 1126: 			break;
 1127: 
 1128: 		default:
 1129: 			if (result) {
 1130: 				AI_SET_PTR(result->var, EG(uninitialized_zval_ptr));
 1131: 				PZVAL_LOCK(EG(uninitialized_zval_ptr));
 1132: 			}
 1133: 			return;
 1134: 			break;
 1135: 	}
 1136: }
 1137: 
 1138: static void zend_fetch_property_address(temp_variable *result, zval **container_ptr, zval *prop_ptr, int type TSRMLS_DC)
 1139: {
 1140: 	zval *container = *container_ptr;;
 1141: 
 1142: 	if (Z_TYPE_P(container) != IS_OBJECT) {
 1143: 		if (container == EG(error_zval_ptr)) {
 1144: 			result->var.ptr_ptr = &EG(error_zval_ptr);
 1145: 			PZVAL_LOCK(*result->var.ptr_ptr);
 1146: 			return;
 1147: 		}
 1148: 
 1149: 		/* this should modify object only if it's empty */
 1150: 		if (type != BP_VAR_UNSET &&
 1151: 		    ((Z_TYPE_P(container) == IS_NULL ||
 1152: 		     (Z_TYPE_P(container) == IS_BOOL && Z_LVAL_P(container)==0) ||
 1153: 		     (Z_TYPE_P(container) == IS_STRING && Z_STRLEN_P(container)==0)))) {
 1154: 			if (!PZVAL_IS_REF(container)) {
 1155: 				SEPARATE_ZVAL(container_ptr);
 1156: 				container = *container_ptr;
 1157: 			}
 1158: 			object_init(container);
 1159: 		} else {
 1160: 			zend_error(E_WARNING, "Attempt to modify property of non-object");
 1161: 			result->var.ptr_ptr = &EG(error_zval_ptr);
 1162: 			PZVAL_LOCK(EG(error_zval_ptr));
 1163: 			return;
 1164: 		}
 1165: 	}
 1166: 
 1167: 	if (Z_OBJ_HT_P(container)->get_property_ptr_ptr) {
 1168: 		zval **ptr_ptr = Z_OBJ_HT_P(container)->get_property_ptr_ptr(container, prop_ptr TSRMLS_CC);
 1169: 		if (NULL == ptr_ptr) {
 1170: 			zval *ptr;
 1171: 
 1172: 			if (Z_OBJ_HT_P(container)->read_property &&
 1173: 				(ptr = Z_OBJ_HT_P(container)->read_property(container, prop_ptr, type TSRMLS_CC)) != NULL) {
 1174: 				AI_SET_PTR(result->var, ptr);
 1175: 				PZVAL_LOCK(ptr);
 1176: 			} else {
 1177: 				zend_error_noreturn(E_ERROR, "Cannot access undefined property for object with overloaded property access");
 1178: 			}
 1179: 		} else {
 1180: 			result->var.ptr_ptr = ptr_ptr;
 1181: 			PZVAL_LOCK(*ptr_ptr);
 1182: 		}
 1183: 	} else if (Z_OBJ_HT_P(container)->read_property) {
 1184: 		zval *ptr = Z_OBJ_HT_P(container)->read_property(container, prop_ptr, type TSRMLS_CC);
 1185: 
 1186: 		AI_SET_PTR(result->var, ptr);
 1187: 		PZVAL_LOCK(ptr);
 1188: 	} else {
 1189: 		zend_error(E_WARNING, "This object doesn't support property references");
 1190: 		result->var.ptr_ptr = &EG(error_zval_ptr);
 1191: 		PZVAL_LOCK(EG(error_zval_ptr));
 1192: 	}
 1193: }
 1194: 
 1195: 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)
 1196: {
 1197: 	zval tmp;
 1198: 	int nest_levels, original_nest_levels;
 1199: 	zend_brk_cont_element *jmp_to;
 1200: 
 1201: 	if (nest_levels_zval->type != IS_LONG) {
 1202: 		tmp = *nest_levels_zval;
 1203: 		zval_copy_ctor(&tmp);
 1204: 		convert_to_long(&tmp);
 1205: 		nest_levels = tmp.value.lval;
 1206: 	} else {
 1207: 		nest_levels = nest_levels_zval->value.lval;
 1208: 	}
 1209: 	original_nest_levels = nest_levels;
 1210: 	do {
 1211: 		if (array_offset==-1) {
 1212: 			zend_error_noreturn(E_ERROR, "Cannot break/continue %d level%s", original_nest_levels, (original_nest_levels == 1) ? "" : "s");
 1213: 		}
 1214: 		jmp_to = &op_array->brk_cont_array[array_offset];
 1215: 		if (nest_levels>1) {
 1216: 			zend_op *brk_opline = &op_array->opcodes[jmp_to->brk];
 1217: 
 1218: 			switch (brk_opline->opcode) {
 1219: 				case ZEND_SWITCH_FREE:
 1220: 					if (brk_opline->op1.u.EA.type != EXT_TYPE_FREE_ON_RETURN) {
 1221: 						zend_switch_free(&T(brk_opline->op1.u.var), brk_opline->extended_value TSRMLS_CC);
 1222: 					}
 1223: 					break;
 1224: 				case ZEND_FREE:
 1225: 					if (brk_opline->op1.u.EA.type != EXT_TYPE_FREE_ON_RETURN) {
 1226: 						zendi_zval_dtor(T(brk_opline->op1.u.var).tmp_var);
 1227: 					}
 1228: 					break;
 1229: 			}
 1230: 		}
 1231: 		array_offset = jmp_to->parent;
 1232: 	} while (--nest_levels > 0);
 1233: 	return jmp_to;
 1234: }
 1235: 
 1236: #if ZEND_INTENSIVE_DEBUGGING
 1237: 
 1238: #define CHECK_SYMBOL_TABLES()														\
 1239: 	zend_hash_apply(&EG(symbol_table), (apply_func_t) zend_check_symbol TSRMLS_CC);	\
 1240: 	if (&EG(symbol_table)!=EG(active_symbol_table)) {								\
 1241: 		zend_hash_apply(EG(active_symbol_table), (apply_func_t) zend_check_symbol TSRMLS_CC);	\
 1242: 	}
 1243: 
 1244: static int zend_check_symbol(zval **pz TSRMLS_DC)
 1245: {
 1246: 	if (Z_TYPE_PP(pz) > 9) {
 1247: 		fprintf(stderr, "Warning!  %x has invalid type!\n", *pz);
 1248: /* See http://support.microsoft.com/kb/190351 */
 1249: #ifdef PHP_WIN32
 1250: 		fflush(stderr);
 1251: #endif
 1252: 	} else if (Z_TYPE_PP(pz) == IS_ARRAY) {
 1253: 		zend_hash_apply(Z_ARRVAL_PP(pz), (apply_func_t) zend_check_symbol TSRMLS_CC);
 1254: 	} else if (Z_TYPE_PP(pz) == IS_OBJECT) {
 1255: 
 1256: 		/* OBJ-TBI - doesn't support new object model! */
 1257: 		zend_hash_apply(Z_OBJPROP_PP(pz), (apply_func_t) zend_check_symbol TSRMLS_CC);
 1258: 	}
 1259: 
 1260: 	return 0;
 1261: }
 1262: 
 1263: 
 1264: #else
 1265: #define CHECK_SYMBOL_TABLES()
 1266: #endif
 1267: 
 1268: ZEND_API opcode_handler_t *zend_opcode_handlers;
 1269: 
 1270: ZEND_API void execute_internal(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC)
 1271: {
 1272: 	zval **return_value_ptr = &(*(temp_variable *)((char *) execute_data_ptr->Ts + execute_data_ptr->opline->result.u.var)).var.ptr;
 1273: 	((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);
 1274: }
 1275: 
 1276: #define ZEND_VM_NEXT_OPCODE() \
 1277: 	CHECK_SYMBOL_TABLES() \
 1278: 	EX(opline)++; \
 1279: 	ZEND_VM_CONTINUE()
 1280: 
 1281: #define ZEND_VM_SET_OPCODE(new_op) \
 1282: 	CHECK_SYMBOL_TABLES() \
 1283: 	EX(opline) = new_op
 1284: 
 1285: #define ZEND_VM_JMP(new_op) \
 1286: 	CHECK_SYMBOL_TABLES() \
 1287: 	if (EXPECTED(!EG(exception))) { \
 1288: 		EX(opline) = new_op; \
 1289: 	} \
 1290: 	ZEND_VM_CONTINUE()
 1291: 
 1292: #define ZEND_VM_INC_OPCODE() \
 1293: 	EX(opline)++
 1294: 
 1295: #include "zend_vm_execute.h"
 1296: 
 1297: ZEND_API int zend_set_user_opcode_handler(zend_uchar opcode, user_opcode_handler_t handler)
 1298: {
 1299: 	if (opcode != ZEND_USER_OPCODE) {
 1300: 		zend_user_opcodes[opcode] = ZEND_USER_OPCODE;
 1301: 		zend_user_opcode_handlers[opcode] = handler;
 1302: 		return SUCCESS;
 1303: 	}
 1304: 	return FAILURE;
 1305: }
 1306: 
 1307: ZEND_API user_opcode_handler_t zend_get_user_opcode_handler(zend_uchar opcode)
 1308: {
 1309: 	return zend_user_opcode_handlers[opcode];
 1310: }
 1311: 
 1312: ZEND_API zval *zend_get_zval_ptr(znode *node, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC) {
 1313: 	return get_zval_ptr(node, Ts, should_free, type);
 1314: }
 1315: 
 1316: ZEND_API zval **zend_get_zval_ptr_ptr(const znode *node, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC) {
 1317: 	return get_zval_ptr_ptr(node, Ts, should_free, type);
 1318: }
 1319: 
 1320: /*
 1321:  * Local variables:
 1322:  * tab-width: 4
 1323:  * c-basic-offset: 4
 1324:  * indent-tabs-mode: t
 1325:  * End:
 1326:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>