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