1/* 2 +----------------------------------------------------------------------+ 3 | Zend Engine | 4 +----------------------------------------------------------------------+ 5 | Copyright (c) 1998-2013 Zend Technologies Ltd. (http://www.zend.com) | 6 +----------------------------------------------------------------------+ 7 | This source file is subject to version 2.00 of the Zend license, | 8 | that is bundled with this package in the file LICENSE, and is | 9 | available through the world-wide-web at the following url: | 10 | http://www.zend.com/license/2_00.txt. | 11 | If you did not receive a copy of the Zend license and are unable to | 12 | obtain it through the world-wide-web, please send a note to | 13 | license@zend.com so we can mail you a copy immediately. | 14 +----------------------------------------------------------------------+ 15 | Authors: Andi Gutmans <andi@zend.com> | 16 | Zeev Suraski <zeev@zend.com> | 17 +----------------------------------------------------------------------+ 18*/ 19 20/* $Id$ */ 21 22#define ZEND_INTENSIVE_DEBUGGING 0 23 24#include <stdio.h> 25#include <signal.h> 26 27#include "zend.h" 28#include "zend_compile.h" 29#include "zend_execute.h" 30#include "zend_API.h" 31#include "zend_ptr_stack.h" 32#include "zend_constants.h" 33#include "zend_extensions.h" 34#include "zend_ini.h" 35#include "zend_exceptions.h" 36#include "zend_interfaces.h" 37#include "zend_closures.h" 38#include "zend_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 49typedef 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 */ 57static void zend_extension_statement_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC); 58static void zend_extension_fcall_begin_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC); 59static 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 68static 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 84static 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 170ZEND_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 175static 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 180static 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 207static 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 218static 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 249static 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 259static 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 287static 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 300static 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 310static 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 323static 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 333static 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 348static 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 358static 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 371static 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 386static 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 */ 429static 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 SEPARATE_ZVAL_IF_NOT_REF(object_ptr); 436 zval_dtor(*object_ptr); 437 object_init(*object_ptr); 438 zend_error(E_STRICT, "Creating default object from empty value"); 439 } 440} 441 442static 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) 443{ 444 *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); 445 446 *class_name = (*pce) ? (*pce)->name: cur_arg_info->class_name; 447 if (*pce && (*pce)->ce_flags & ZEND_ACC_INTERFACE) { 448 return "implement interface "; 449 } else { 450 return "be an instance of "; 451 } 452} 453 454static 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) 455{ 456 zend_execute_data *ptr = EG(current_execute_data)->prev_execute_data; 457 char *fname = zf->common.function_name; 458 char *fsep; 459 char *fclass; 460 461 if (zf->common.scope) { 462 fsep = "::"; 463 fclass = zf->common.scope->name; 464 } else { 465 fsep = ""; 466 fclass = ""; 467 } 468 469 if (ptr && ptr->op_array) { 470 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); 471 } else { 472 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); 473 } 474 return 0; 475} 476 477static inline int zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zval *arg, ulong fetch_type TSRMLS_DC) 478{ 479 zend_arg_info *cur_arg_info; 480 char *need_msg; 481 zend_class_entry *ce; 482 483 if (!zf->common.arg_info 484 || arg_num>zf->common.num_args) { 485 return 1; 486 } 487 488 cur_arg_info = &zf->common.arg_info[arg_num-1]; 489 490 if (cur_arg_info->class_name) { 491 const char *class_name; 492 493 if (!arg) { 494 need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC); 495 return zend_verify_arg_error(zf, arg_num, cur_arg_info, need_msg, class_name, "none", "" TSRMLS_CC); 496 } 497 if (Z_TYPE_P(arg) == IS_OBJECT) { 498 need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC); 499 if (!ce || !instanceof_function(Z_OBJCE_P(arg), ce TSRMLS_CC)) { 500 return zend_verify_arg_error(zf, arg_num, cur_arg_info, need_msg, class_name, "instance of ", Z_OBJCE_P(arg)->name TSRMLS_CC); 501 } 502 } else if (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null) { 503 need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC); 504 return zend_verify_arg_error(zf, arg_num, cur_arg_info, need_msg, class_name, zend_zval_type_name(arg), "" TSRMLS_CC); 505 } 506 } else if (cur_arg_info->array_type_hint) { 507 if (!arg) { 508 return zend_verify_arg_error(zf, arg_num, cur_arg_info, "be an array", "", "none", "" TSRMLS_CC); 509 } 510 if (Z_TYPE_P(arg) != IS_ARRAY && (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null)) { 511 return zend_verify_arg_error(zf, arg_num, cur_arg_info, "be an array", "", zend_zval_type_name(arg), "" TSRMLS_CC); 512 } 513 } 514 return 1; 515} 516 517static 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) 518 519{ 520 zval *object = *object_ptr; 521 zend_free_op free_value; 522 zval *value = get_zval_ptr(value_op, Ts, &free_value, BP_VAR_R); 523 zval **retval = &T(result->u.var).var.ptr; 524 525 if (Z_TYPE_P(object) != IS_OBJECT) { 526 if (object == EG(error_zval_ptr)) { 527 if (!RETURN_VALUE_UNUSED(result)) { 528 *retval = EG(uninitialized_zval_ptr); 529 PZVAL_LOCK(*retval); 530 } 531 FREE_OP(free_value); 532 return; 533 } 534 if (Z_TYPE_P(object) == IS_NULL || 535 (Z_TYPE_P(object) == IS_BOOL && Z_LVAL_P(object) == 0) || 536 (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0)) { 537 SEPARATE_ZVAL_IF_NOT_REF(object_ptr); 538 object = *object_ptr; 539 Z_ADDREF_P(object); 540 zend_error(E_STRICT, "Creating default object from empty value"); 541 if (Z_REFCOUNT_P(object) == 1) { 542 /* object was removed by error handler, nothing to assign to */ 543 zval_ptr_dtor(&object); 544 if (retval) { 545 *retval = &EG(uninitialized_zval); 546 PZVAL_LOCK(*retval); 547 } 548 FREE_OP(free_value); 549 return; 550 } 551 Z_DELREF_P(object); 552 zval_dtor(object); 553 object_init(object); 554 } else { 555 zend_error(E_WARNING, "Attempt to assign property of non-object"); 556 if (!RETURN_VALUE_UNUSED(result)) { 557 *retval = EG(uninitialized_zval_ptr); 558 PZVAL_LOCK(*retval); 559 } 560 FREE_OP(free_value); 561 return; 562 } 563 } 564 565 /* separate our value if necessary */ 566 if (value_op->op_type == IS_TMP_VAR) { 567 zval *orig_value = value; 568 569 ALLOC_ZVAL(value); 570 *value = *orig_value; 571 Z_UNSET_ISREF_P(value); 572 Z_SET_REFCOUNT_P(value, 0); 573 } else if (value_op->op_type == IS_CONST) { 574 zval *orig_value = value; 575 576 ALLOC_ZVAL(value); 577 *value = *orig_value; 578 Z_UNSET_ISREF_P(value); 579 Z_SET_REFCOUNT_P(value, 0); 580 zval_copy_ctor(value); 581 } 582 583 584 Z_ADDREF_P(value); 585 if (opcode == ZEND_ASSIGN_OBJ) { 586 if (!Z_OBJ_HT_P(object)->write_property) { 587 zend_error(E_WARNING, "Attempt to assign property of non-object"); 588 if (!RETURN_VALUE_UNUSED(result)) { 589 *retval = EG(uninitialized_zval_ptr); 590 PZVAL_LOCK(*retval); 591 } 592 if (value_op->op_type == IS_TMP_VAR) { 593 FREE_ZVAL(value); 594 } else if (value_op->op_type == IS_CONST) { 595 zval_ptr_dtor(&value); 596 } 597 FREE_OP(free_value); 598 return; 599 } 600 Z_OBJ_HT_P(object)->write_property(object, property_name, value TSRMLS_CC); 601 } else { 602 /* Note: property_name in this case is really the array index! */ 603 if (!Z_OBJ_HT_P(object)->write_dimension) { 604 zend_error_noreturn(E_ERROR, "Cannot use object as array"); 605 } 606 Z_OBJ_HT_P(object)->write_dimension(object, property_name, value TSRMLS_CC); 607 } 608 609 if (!RETURN_VALUE_UNUSED(result) && !EG(exception)) { 610 AI_SET_PTR(T(result->u.var).var, value); 611 PZVAL_LOCK(value); 612 } 613 zval_ptr_dtor(&value); 614 FREE_OP_IF_VAR(free_value); 615} 616 617static inline int zend_assign_to_string_offset(const temp_variable *T, const zval *value, int value_type TSRMLS_DC) 618{ 619 if (Z_TYPE_P(T->str_offset.str) == IS_STRING) { 620 621 if (((int)T->str_offset.offset < 0)) { 622 zend_error(E_WARNING, "Illegal string offset: %d", T->str_offset.offset); 623 return 0; 624 } 625 626 if (T->str_offset.offset >= Z_STRLEN_P(T->str_offset.str)) { 627 Z_STRVAL_P(T->str_offset.str) = (char *) erealloc(Z_STRVAL_P(T->str_offset.str), T->str_offset.offset+1+1); 628 memset(Z_STRVAL_P(T->str_offset.str) + Z_STRLEN_P(T->str_offset.str), 629 ' ', 630 T->str_offset.offset - Z_STRLEN_P(T->str_offset.str)); 631 Z_STRVAL_P(T->str_offset.str)[T->str_offset.offset+1] = 0; 632 Z_STRLEN_P(T->str_offset.str) = T->str_offset.offset+1; 633 } 634 635 if (Z_TYPE_P(value) != IS_STRING) { 636 zval tmp = *value; 637 638 if (value_type != IS_TMP_VAR) { 639 zval_copy_ctor(&tmp); 640 } 641 convert_to_string(&tmp); 642 Z_STRVAL_P(T->str_offset.str)[T->str_offset.offset] = Z_STRVAL(tmp)[0]; 643 STR_FREE(Z_STRVAL(tmp)); 644 } else { 645 Z_STRVAL_P(T->str_offset.str)[T->str_offset.offset] = Z_STRVAL_P(value)[0]; 646 if (value_type == IS_TMP_VAR) { 647 /* we can safely free final_value here 648 * because separation is done only 649 * in case value_type == IS_VAR */ 650 STR_FREE(Z_STRVAL_P(value)); 651 } 652 } 653 /* 654 * the value of an assignment to a string offset is undefined 655 T(result->u.var).var = &T->str_offset.str; 656 */ 657 } 658 return 1; 659} 660 661static inline zval* zend_assign_to_variable(zval **variable_ptr_ptr, zval *value, int is_tmp_var TSRMLS_DC) 662{ 663 zval *variable_ptr = *variable_ptr_ptr; 664 zval garbage; 665 666 if (variable_ptr == EG(error_zval_ptr)) { 667 if (is_tmp_var) { 668 zval_dtor(value); 669 } 670 return EG(uninitialized_zval_ptr); 671 } 672 673 if (Z_TYPE_P(variable_ptr) == IS_OBJECT && Z_OBJ_HANDLER_P(variable_ptr, set)) { 674 Z_OBJ_HANDLER_P(variable_ptr, set)(variable_ptr_ptr, value TSRMLS_CC); 675 return variable_ptr; 676 } 677 678 if (PZVAL_IS_REF(variable_ptr)) { 679 if (variable_ptr!=value) { 680 zend_uint refcount = Z_REFCOUNT_P(variable_ptr); 681 682 garbage = *variable_ptr; 683 *variable_ptr = *value; 684 Z_SET_REFCOUNT_P(variable_ptr, refcount); 685 Z_SET_ISREF_P(variable_ptr); 686 if (!is_tmp_var) { 687 zendi_zval_copy_ctor(*variable_ptr); 688 } 689 zendi_zval_dtor(garbage); 690 return variable_ptr; 691 } 692 } else { 693 if (Z_DELREF_P(variable_ptr)==0) { 694 if (!is_tmp_var) { 695 if (variable_ptr==value) { 696 Z_ADDREF_P(variable_ptr); 697 } else if (PZVAL_IS_REF(value)) { 698 garbage = *variable_ptr; 699 *variable_ptr = *value; 700 INIT_PZVAL(variable_ptr); 701 zval_copy_ctor(variable_ptr); 702 zendi_zval_dtor(garbage); 703 return variable_ptr; 704 } else { 705 Z_ADDREF_P(value); 706 *variable_ptr_ptr = value; 707 if (variable_ptr != &EG(uninitialized_zval)) { 708 GC_REMOVE_ZVAL_FROM_BUFFER(variable_ptr); 709 zval_dtor(variable_ptr); 710 efree(variable_ptr); 711 } 712 return value; 713 } 714 } else { 715 garbage = *variable_ptr; 716 *variable_ptr = *value; 717 INIT_PZVAL(variable_ptr); 718 zendi_zval_dtor(garbage); 719 return variable_ptr; 720 } 721 } else { /* we need to split */ 722 GC_ZVAL_CHECK_POSSIBLE_ROOT(*variable_ptr_ptr); 723 if (!is_tmp_var) { 724 if (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) { 725 ALLOC_ZVAL(variable_ptr); 726 *variable_ptr_ptr = variable_ptr; 727 *variable_ptr = *value; 728 Z_SET_REFCOUNT_P(variable_ptr, 1); 729 zval_copy_ctor(variable_ptr); 730 } else { 731 *variable_ptr_ptr = value; 732 Z_ADDREF_P(value); 733 } 734 } else { 735 ALLOC_ZVAL(*variable_ptr_ptr); 736 Z_SET_REFCOUNT_P(value, 1); 737 **variable_ptr_ptr = *value; 738 } 739 } 740 Z_UNSET_ISREF_PP(variable_ptr_ptr); 741 } 742 743 return *variable_ptr_ptr; 744} 745 746 747/* Utility Functions for Extensions */ 748static void zend_extension_statement_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC) 749{ 750 if (extension->statement_handler) { 751 extension->statement_handler(op_array); 752 } 753} 754 755 756static void zend_extension_fcall_begin_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC) 757{ 758 if (extension->fcall_begin_handler) { 759 extension->fcall_begin_handler(op_array); 760 } 761} 762 763 764static void zend_extension_fcall_end_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC) 765{ 766 if (extension->fcall_end_handler) { 767 extension->fcall_end_handler(op_array); 768 } 769} 770 771 772static inline HashTable *zend_get_target_symbol_table(const zend_op *opline, const temp_variable *Ts, int type, const zval *variable TSRMLS_DC) 773{ 774 switch (opline->op2.u.EA.type) { 775 case ZEND_FETCH_LOCAL: 776 if (!EG(active_symbol_table)) { 777 zend_rebuild_symbol_table(TSRMLS_C); 778 } 779 return EG(active_symbol_table); 780 break; 781 case ZEND_FETCH_GLOBAL: 782 case ZEND_FETCH_GLOBAL_LOCK: 783 return &EG(symbol_table); 784 break; 785 case ZEND_FETCH_STATIC: 786 if (!EG(active_op_array)->static_variables) { 787 ALLOC_HASHTABLE(EG(active_op_array)->static_variables); 788 zend_hash_init(EG(active_op_array)->static_variables, 2, NULL, ZVAL_PTR_DTOR, 0); 789 } 790 return EG(active_op_array)->static_variables; 791 break; 792 EMPTY_SWITCH_DEFAULT_CASE() 793 } 794 return NULL; 795} 796 797static inline zval **zend_fetch_dimension_address_inner(HashTable *ht, const zval *dim, int type TSRMLS_DC) 798{ 799 zval **retval; 800 char *offset_key; 801 int offset_key_length; 802 long index; 803 804 switch (dim->type) { 805 case IS_NULL: 806 offset_key = ""; 807 offset_key_length = 0; 808 goto fetch_string_dim; 809 810 case IS_STRING: 811 812 offset_key = dim->value.str.val; 813 offset_key_length = dim->value.str.len; 814 815fetch_string_dim: 816 if (zend_symtable_find(ht, offset_key, offset_key_length+1, (void **) &retval) == FAILURE) { 817 switch (type) { 818 case BP_VAR_R: 819 zend_error(E_NOTICE, "Undefined index: %s", offset_key); 820 /* break missing intentionally */ 821 case BP_VAR_UNSET: 822 case BP_VAR_IS: 823 retval = &EG(uninitialized_zval_ptr); 824 break; 825 case BP_VAR_RW: 826 zend_error(E_NOTICE,"Undefined index: %s", offset_key); 827 /* break missing intentionally */ 828 case BP_VAR_W: { 829 zval *new_zval = &EG(uninitialized_zval); 830 831 Z_ADDREF_P(new_zval); 832 zend_symtable_update(ht, offset_key, offset_key_length+1, &new_zval, sizeof(zval *), (void **) &retval); 833 } 834 break; 835 } 836 } 837 break; 838 case IS_DOUBLE: 839 index = zend_dval_to_lval(Z_DVAL_P(dim)); 840 goto num_index; 841 case IS_RESOURCE: 842 zend_error(E_STRICT, "Resource ID#%ld used as offset, casting to integer (%ld)", Z_LVAL_P(dim), Z_LVAL_P(dim)); 843 /* Fall Through */ 844 case IS_BOOL: 845 case IS_LONG: 846 index = Z_LVAL_P(dim); 847num_index: 848 if (zend_hash_index_find(ht, index, (void **) &retval) == FAILURE) { 849 switch (type) { 850 case BP_VAR_R: 851 zend_error(E_NOTICE,"Undefined offset: %ld", index); 852 /* break missing intentionally */ 853 case BP_VAR_UNSET: 854 case BP_VAR_IS: 855 retval = &EG(uninitialized_zval_ptr); 856 break; 857 case BP_VAR_RW: 858 zend_error(E_NOTICE,"Undefined offset: %ld", index); 859 /* break missing intentionally */ 860 case BP_VAR_W: { 861 zval *new_zval = &EG(uninitialized_zval); 862 863 Z_ADDREF_P(new_zval); 864 zend_hash_index_update(ht, index, &new_zval, sizeof(zval *), (void **) &retval); 865 } 866 break; 867 } 868 } 869 break; 870 871 default: 872 zend_error(E_WARNING, "Illegal offset type"); 873 return (type == BP_VAR_W || type == BP_VAR_RW) ? 874 &EG(error_zval_ptr) : &EG(uninitialized_zval_ptr); 875 } 876 return retval; 877} 878 879static void zend_fetch_dimension_address(temp_variable *result, zval **container_ptr, zval *dim, int dim_is_tmp_var, int type TSRMLS_DC) 880{ 881 zval *container = *container_ptr; 882 zval **retval; 883 884 switch (Z_TYPE_P(container)) { 885 886 case IS_ARRAY: 887 if (type != BP_VAR_UNSET && Z_REFCOUNT_P(container)>1 && !PZVAL_IS_REF(container)) { 888 SEPARATE_ZVAL(container_ptr); 889 container = *container_ptr; 890 } 891fetch_from_array: 892 if (dim == NULL) { 893 zval *new_zval = &EG(uninitialized_zval); 894 895 Z_ADDREF_P(new_zval); 896 if (zend_hash_next_index_insert(Z_ARRVAL_P(container), &new_zval, sizeof(zval *), (void **) &retval) == FAILURE) { 897 zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied"); 898 retval = &EG(error_zval_ptr); 899 Z_DELREF_P(new_zval); 900 } 901 } else { 902 retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, type TSRMLS_CC); 903 } 904 result->var.ptr_ptr = retval; 905 PZVAL_LOCK(*retval); 906 return; 907 break; 908 909 case IS_NULL: 910 if (container == EG(error_zval_ptr)) { 911 result->var.ptr_ptr = &EG(error_zval_ptr); 912 PZVAL_LOCK(EG(error_zval_ptr)); 913 } else if (type != BP_VAR_UNSET) { 914convert_to_array: 915 if (!PZVAL_IS_REF(container)) { 916 SEPARATE_ZVAL(container_ptr); 917 container = *container_ptr; 918 } 919 zval_dtor(container); 920 array_init(container); 921 goto fetch_from_array; 922 } else { 923 /* for read-mode only */ 924 result->var.ptr_ptr = &EG(uninitialized_zval_ptr); 925 PZVAL_LOCK(EG(uninitialized_zval_ptr)); 926 } 927 return; 928 break; 929 930 case IS_STRING: { 931 zval tmp; 932 933 if (type != BP_VAR_UNSET && Z_STRLEN_P(container)==0) { 934 goto convert_to_array; 935 } 936 if (dim == NULL) { 937 zend_error_noreturn(E_ERROR, "[] operator not supported for strings"); 938 } 939 940 if (type != BP_VAR_UNSET) { 941 SEPARATE_ZVAL_IF_NOT_REF(container_ptr); 942 } 943 944 if (Z_TYPE_P(dim) != IS_LONG) { 945 switch(Z_TYPE_P(dim)) { 946 /* case IS_LONG: */ 947 case IS_STRING: 948 case IS_DOUBLE: 949 case IS_NULL: 950 case IS_BOOL: 951 /* do nothing */ 952 break; 953 default: 954 zend_error(E_WARNING, "Illegal offset type"); 955 break; 956 } 957 958 tmp = *dim; 959 zval_copy_ctor(&tmp); 960 convert_to_long(&tmp); 961 dim = &tmp; 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 1035static 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 1138static 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 1195static 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 1244static 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 1268ZEND_API opcode_handler_t *zend_opcode_handlers; 1269 1270ZEND_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 1297ZEND_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 1307ZEND_API user_opcode_handler_t zend_get_user_opcode_handler(zend_uchar opcode) 1308{ 1309 return zend_user_opcode_handlers[opcode]; 1310} 1311 1312ZEND_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 1316ZEND_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 */ 1327