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#include <stdio.h> 23#include <signal.h> 24 25#include "zend.h" 26#include "zend_compile.h" 27#include "zend_execute.h" 28#include "zend_API.h" 29#include "zend_ptr_stack.h" 30#include "zend_constants.h" 31#include "zend_extensions.h" 32#include "zend_exceptions.h" 33#include "zend_closures.h" 34#include "zend_generators.h" 35#include "zend_vm.h" 36#include "zend_float.h" 37#ifdef HAVE_SYS_TIME_H 38#include <sys/time.h> 39#endif 40 41ZEND_API void (*zend_execute_ex)(zend_execute_data *execute_data TSRMLS_DC); 42ZEND_API void (*zend_execute_internal)(zend_execute_data *execute_data_ptr, zend_fcall_info *fci, int return_value_used TSRMLS_DC); 43 44/* true globals */ 45ZEND_API const zend_fcall_info empty_fcall_info = { 0, NULL, NULL, NULL, NULL, 0, NULL, NULL, 0 }; 46ZEND_API const zend_fcall_info_cache empty_fcall_info_cache = { 0, NULL, NULL, NULL, NULL }; 47 48#ifdef ZEND_WIN32 49#include <process.h> 50static WNDCLASS wc; 51static HWND timeout_window; 52static HANDLE timeout_thread_event; 53static HANDLE timeout_thread_handle; 54static DWORD timeout_thread_id; 55static int timeout_thread_initialized=0; 56#endif 57 58#if 0&&ZEND_DEBUG 59static void (*original_sigsegv_handler)(int); 60static void zend_handle_sigsegv(int dummy) /* {{{ */ 61{ 62 fflush(stdout); 63 fflush(stderr); 64 if (original_sigsegv_handler == zend_handle_sigsegv) { 65 signal(SIGSEGV, original_sigsegv_handler); 66 } else { 67 signal(SIGSEGV, SIG_DFL); 68 } 69 { 70 TSRMLS_FETCH(); 71 72 fprintf(stderr, "SIGSEGV caught on opcode %d on opline %d of %s() at %s:%d\n\n", 73 active_opline->opcode, 74 active_opline-EG(active_op_array)->opcodes, 75 get_active_function_name(TSRMLS_C), 76 zend_get_executed_filename(TSRMLS_C), 77 zend_get_executed_lineno(TSRMLS_C)); 78/* See http://support.microsoft.com/kb/190351 */ 79#ifdef PHP_WIN32 80 fflush(stderr); 81#endif 82 } 83 if (original_sigsegv_handler!=zend_handle_sigsegv) { 84 original_sigsegv_handler(dummy); 85 } 86} 87/* }}} */ 88#endif 89 90static void zend_extension_activator(zend_extension *extension TSRMLS_DC) /* {{{ */ 91{ 92 if (extension->activate) { 93 extension->activate(); 94 } 95} 96/* }}} */ 97 98static void zend_extension_deactivator(zend_extension *extension TSRMLS_DC) /* {{{ */ 99{ 100 if (extension->deactivate) { 101 extension->deactivate(); 102 } 103} 104/* }}} */ 105 106static int clean_non_persistent_function(zend_function *function TSRMLS_DC) /* {{{ */ 107{ 108 return (function->type == ZEND_INTERNAL_FUNCTION) ? ZEND_HASH_APPLY_STOP : ZEND_HASH_APPLY_REMOVE; 109} 110/* }}} */ 111 112static int clean_non_persistent_function_full(zend_function *function TSRMLS_DC) /* {{{ */ 113{ 114 return (function->type == ZEND_INTERNAL_FUNCTION) ? ZEND_HASH_APPLY_KEEP : ZEND_HASH_APPLY_REMOVE; 115} 116/* }}} */ 117 118static int clean_non_persistent_class(zend_class_entry **ce TSRMLS_DC) /* {{{ */ 119{ 120 return ((*ce)->type == ZEND_INTERNAL_CLASS) ? ZEND_HASH_APPLY_STOP : ZEND_HASH_APPLY_REMOVE; 121} 122/* }}} */ 123 124static int clean_non_persistent_class_full(zend_class_entry **ce TSRMLS_DC) /* {{{ */ 125{ 126 return ((*ce)->type == ZEND_INTERNAL_CLASS) ? ZEND_HASH_APPLY_KEEP : ZEND_HASH_APPLY_REMOVE; 127} 128/* }}} */ 129 130void init_executor(TSRMLS_D) /* {{{ */ 131{ 132 zend_init_fpu(TSRMLS_C); 133 134 INIT_ZVAL(EG(uninitialized_zval)); 135 /* trick to make uninitialized_zval never be modified, passed by ref, etc. */ 136 Z_ADDREF(EG(uninitialized_zval)); 137 INIT_ZVAL(EG(error_zval)); 138 EG(uninitialized_zval_ptr)=&EG(uninitialized_zval); 139 EG(error_zval_ptr)=&EG(error_zval); 140/* destroys stack frame, therefore makes core dumps worthless */ 141#if 0&&ZEND_DEBUG 142 original_sigsegv_handler = signal(SIGSEGV, zend_handle_sigsegv); 143#endif 144 EG(return_value_ptr_ptr) = NULL; 145 146 EG(symtable_cache_ptr) = EG(symtable_cache) - 1; 147 EG(symtable_cache_limit) = EG(symtable_cache) + SYMTABLE_CACHE_SIZE - 1; 148 EG(no_extensions) = 0; 149 150 EG(function_table) = CG(function_table); 151 EG(class_table) = CG(class_table); 152 153 EG(in_execution) = 0; 154 EG(in_autoload) = NULL; 155 EG(autoload_func) = NULL; 156 EG(error_handling) = EH_NORMAL; 157 158 zend_vm_stack_init(TSRMLS_C); 159 zend_vm_stack_push((void *) NULL TSRMLS_CC); 160 161 zend_hash_init(&EG(symbol_table), 50, NULL, ZVAL_PTR_DTOR, 0); 162 EG(active_symbol_table) = &EG(symbol_table); 163 164 zend_llist_apply(&zend_extensions, (llist_apply_func_t) zend_extension_activator TSRMLS_CC); 165 EG(opline_ptr) = NULL; 166 167 zend_hash_init(&EG(included_files), 5, NULL, NULL, 0); 168 169 EG(ticks_count) = 0; 170 171 EG(user_error_handler) = NULL; 172 173 EG(current_execute_data) = NULL; 174 175 zend_stack_init(&EG(user_error_handlers_error_reporting)); 176 zend_ptr_stack_init(&EG(user_error_handlers)); 177 zend_ptr_stack_init(&EG(user_exception_handlers)); 178 179 zend_objects_store_init(&EG(objects_store), 1024); 180 181 EG(full_tables_cleanup) = 0; 182#ifdef ZEND_WIN32 183 EG(timed_out) = 0; 184#endif 185 186 EG(exception) = NULL; 187 EG(prev_exception) = NULL; 188 189 EG(scope) = NULL; 190 EG(called_scope) = NULL; 191 192 EG(This) = NULL; 193 194 EG(active_op_array) = NULL; 195 196 EG(active) = 1; 197 EG(start_op) = NULL; 198} 199/* }}} */ 200 201static int zval_call_destructor(zval **zv TSRMLS_DC) /* {{{ */ 202{ 203 if (Z_TYPE_PP(zv) == IS_OBJECT && Z_REFCOUNT_PP(zv) == 1) { 204 return ZEND_HASH_APPLY_REMOVE; 205 } else { 206 return ZEND_HASH_APPLY_KEEP; 207 } 208} 209/* }}} */ 210 211void shutdown_destructors(TSRMLS_D) /* {{{ */ 212{ 213 zend_try { 214 int symbols; 215 do { 216 symbols = zend_hash_num_elements(&EG(symbol_table)); 217 zend_hash_reverse_apply(&EG(symbol_table), (apply_func_t) zval_call_destructor TSRMLS_CC); 218 } while (symbols != zend_hash_num_elements(&EG(symbol_table))); 219 zend_objects_store_call_destructors(&EG(objects_store) TSRMLS_CC); 220 } zend_catch { 221 /* if we couldn't destruct cleanly, mark all objects as destructed anyway */ 222 zend_objects_store_mark_destructed(&EG(objects_store) TSRMLS_CC); 223 } zend_end_try(); 224} 225/* }}} */ 226 227void shutdown_executor(TSRMLS_D) /* {{{ */ 228{ 229 zend_try { 230 231/* Removed because this can not be safely done, e.g. in this situation: 232 Object 1 creates object 2 233 Object 3 holds reference to object 2. 234 Now when 1 and 2 are destroyed, 3 can still access 2 in its destructor, with 235 very problematic results */ 236/* zend_objects_store_call_destructors(&EG(objects_store) TSRMLS_CC); */ 237 238/* Moved after symbol table cleaners, because some of the cleaners can call 239 destructors, which would use EG(symtable_cache_ptr) and thus leave leaks */ 240/* while (EG(symtable_cache_ptr)>=EG(symtable_cache)) { 241 zend_hash_destroy(*EG(symtable_cache_ptr)); 242 efree(*EG(symtable_cache_ptr)); 243 EG(symtable_cache_ptr)--; 244 } 245*/ 246 zend_llist_apply(&zend_extensions, (llist_apply_func_t) zend_extension_deactivator TSRMLS_CC); 247 zend_hash_graceful_reverse_destroy(&EG(symbol_table)); 248 } zend_end_try(); 249 250 zend_try { 251 zval *zeh; 252 /* remove error handlers before destroying classes and functions, 253 * so that if handler used some class, crash would not happen */ 254 if (EG(user_error_handler)) { 255 zeh = EG(user_error_handler); 256 EG(user_error_handler) = NULL; 257 zval_ptr_dtor(&zeh); 258 } 259 260 if (EG(user_exception_handler)) { 261 zeh = EG(user_exception_handler); 262 EG(user_exception_handler) = NULL; 263 zval_ptr_dtor(&zeh); 264 } 265 266 zend_stack_destroy(&EG(user_error_handlers_error_reporting)); 267 zend_stack_init(&EG(user_error_handlers_error_reporting)); 268 zend_ptr_stack_clean(&EG(user_error_handlers), ZVAL_DESTRUCTOR, 1); 269 zend_ptr_stack_clean(&EG(user_exception_handlers), ZVAL_DESTRUCTOR, 1); 270 } zend_end_try(); 271 272 zend_try { 273 /* Cleanup static data for functions and arrays. 274 * We need a separate cleanup stage because of the following problem: 275 * Suppose we destroy class X, which destroys the class's function table, 276 * and in the function table we have function foo() that has static $bar. 277 * Now if an object of class X is assigned to $bar, its destructor will be 278 * called and will fail since X's function table is in mid-destruction. 279 * So we want first of all to clean up all data and then move to tables destruction. 280 * Note that only run-time accessed data need to be cleaned up, pre-defined data can 281 * not contain objects and thus are not probelmatic */ 282 if (EG(full_tables_cleanup)) { 283 zend_hash_apply(EG(function_table), (apply_func_t) zend_cleanup_function_data_full TSRMLS_CC); 284 zend_hash_apply(EG(class_table), (apply_func_t) zend_cleanup_class_data TSRMLS_CC); 285 } else { 286 zend_hash_reverse_apply(EG(function_table), (apply_func_t) zend_cleanup_function_data TSRMLS_CC); 287 zend_hash_reverse_apply(EG(class_table), (apply_func_t) zend_cleanup_user_class_data TSRMLS_CC); 288 zend_cleanup_internal_classes(TSRMLS_C); 289 } 290 } zend_end_try(); 291 292 zend_try { 293 zend_objects_store_free_object_storage(&EG(objects_store) TSRMLS_CC); 294 295 zend_vm_stack_destroy(TSRMLS_C); 296 297 /* Destroy all op arrays */ 298 if (EG(full_tables_cleanup)) { 299 zend_hash_reverse_apply(EG(function_table), (apply_func_t) clean_non_persistent_function_full TSRMLS_CC); 300 zend_hash_reverse_apply(EG(class_table), (apply_func_t) clean_non_persistent_class_full TSRMLS_CC); 301 } else { 302 zend_hash_reverse_apply(EG(function_table), (apply_func_t) clean_non_persistent_function TSRMLS_CC); 303 zend_hash_reverse_apply(EG(class_table), (apply_func_t) clean_non_persistent_class TSRMLS_CC); 304 } 305 306 while (EG(symtable_cache_ptr)>=EG(symtable_cache)) { 307 zend_hash_destroy(*EG(symtable_cache_ptr)); 308 FREE_HASHTABLE(*EG(symtable_cache_ptr)); 309 EG(symtable_cache_ptr)--; 310 } 311 } zend_end_try(); 312 313 zend_try { 314 clean_non_persistent_constants(TSRMLS_C); 315 } zend_end_try(); 316 317 zend_try { 318#if 0&&ZEND_DEBUG 319 signal(SIGSEGV, original_sigsegv_handler); 320#endif 321 322 zend_hash_destroy(&EG(included_files)); 323 324 zend_stack_destroy(&EG(user_error_handlers_error_reporting)); 325 zend_ptr_stack_destroy(&EG(user_error_handlers)); 326 zend_ptr_stack_destroy(&EG(user_exception_handlers)); 327 zend_objects_store_destroy(&EG(objects_store)); 328 if (EG(in_autoload)) { 329 zend_hash_destroy(EG(in_autoload)); 330 FREE_HASHTABLE(EG(in_autoload)); 331 } 332 } zend_end_try(); 333 334 zend_shutdown_fpu(TSRMLS_C); 335 336 EG(active) = 0; 337} 338/* }}} */ 339 340/* return class name and "::" or "". */ 341ZEND_API const char *get_active_class_name(const char **space TSRMLS_DC) /* {{{ */ 342{ 343 if (!zend_is_executing(TSRMLS_C)) { 344 if (space) { 345 *space = ""; 346 } 347 return ""; 348 } 349 switch (EG(current_execute_data)->function_state.function->type) { 350 case ZEND_USER_FUNCTION: 351 case ZEND_INTERNAL_FUNCTION: 352 { 353 zend_class_entry *ce = EG(current_execute_data)->function_state.function->common.scope; 354 355 if (space) { 356 *space = ce ? "::" : ""; 357 } 358 return ce ? ce->name : ""; 359 } 360 default: 361 if (space) { 362 *space = ""; 363 } 364 return ""; 365 } 366} 367/* }}} */ 368 369ZEND_API const char *get_active_function_name(TSRMLS_D) /* {{{ */ 370{ 371 if (!zend_is_executing(TSRMLS_C)) { 372 return NULL; 373 } 374 switch (EG(current_execute_data)->function_state.function->type) { 375 case ZEND_USER_FUNCTION: { 376 const char *function_name = ((zend_op_array *) EG(current_execute_data)->function_state.function)->function_name; 377 378 if (function_name) { 379 return function_name; 380 } else { 381 return "main"; 382 } 383 } 384 break; 385 case ZEND_INTERNAL_FUNCTION: 386 return ((zend_internal_function *) EG(current_execute_data)->function_state.function)->function_name; 387 break; 388 default: 389 return NULL; 390 } 391} 392/* }}} */ 393 394ZEND_API const char *zend_get_executed_filename(TSRMLS_D) /* {{{ */ 395{ 396 if (EG(active_op_array)) { 397 return EG(active_op_array)->filename; 398 } else { 399 return "[no active file]"; 400 } 401} 402/* }}} */ 403 404ZEND_API uint zend_get_executed_lineno(TSRMLS_D) /* {{{ */ 405{ 406 if(EG(exception) && EG(opline_ptr) && active_opline->opcode == ZEND_HANDLE_EXCEPTION && 407 active_opline->lineno == 0 && EG(opline_before_exception)) { 408 return EG(opline_before_exception)->lineno; 409 } 410 if (EG(opline_ptr)) { 411 return active_opline->lineno; 412 } else { 413 return 0; 414 } 415} 416/* }}} */ 417 418ZEND_API zend_bool zend_is_executing(TSRMLS_D) /* {{{ */ 419{ 420 return EG(in_execution); 421} 422/* }}} */ 423 424ZEND_API void _zval_ptr_dtor(zval **zval_ptr ZEND_FILE_LINE_DC) /* {{{ */ 425{ 426 i_zval_ptr_dtor(*zval_ptr ZEND_FILE_LINE_RELAY_CC); 427} 428/* }}} */ 429 430ZEND_API void _zval_internal_ptr_dtor(zval **zval_ptr ZEND_FILE_LINE_DC) /* {{{ */ 431{ 432#if DEBUG_ZEND>=2 433 printf("Reducing refcount for %x (%x): %d->%d\n", *zval_ptr, zval_ptr, Z_REFCOUNT_PP(zval_ptr), Z_REFCOUNT_PP(zval_ptr) - 1); 434#endif 435 Z_DELREF_PP(zval_ptr); 436 if (Z_REFCOUNT_PP(zval_ptr) == 0) { 437 zval_internal_dtor(*zval_ptr); 438 free(*zval_ptr); 439 } else if (Z_REFCOUNT_PP(zval_ptr) == 1) { 440 Z_UNSET_ISREF_PP(zval_ptr); 441 } 442} 443/* }}} */ 444 445ZEND_API int zend_is_true(zval *op) /* {{{ */ 446{ 447 return i_zend_is_true(op); 448} 449/* }}} */ 450 451#include "../TSRM/tsrm_strtok_r.h" 452 453#define IS_VISITED_CONSTANT IS_CONSTANT_INDEX 454#define IS_CONSTANT_VISITED(p) (Z_TYPE_P(p) & IS_VISITED_CONSTANT) 455#define Z_REAL_TYPE_P(p) (Z_TYPE_P(p) & ~IS_VISITED_CONSTANT) 456#define MARK_CONSTANT_VISITED(p) Z_TYPE_P(p) |= IS_VISITED_CONSTANT 457 458static void zval_deep_copy(zval **p) 459{ 460 zval *value; 461 462 ALLOC_ZVAL(value); 463 *value = **p; 464 Z_TYPE_P(value) &= ~IS_CONSTANT_INDEX; 465 zval_copy_ctor(value); 466 Z_TYPE_P(value) = Z_TYPE_PP(p); 467 INIT_PZVAL(value); 468 *p = value; 469} 470 471ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *scope TSRMLS_DC) /* {{{ */ 472{ 473 zval *p = *pp; 474 zend_bool inline_change = (zend_bool) (zend_uintptr_t) arg; 475 zval const_value; 476 char *colon; 477 478 if (IS_CONSTANT_VISITED(p)) { 479 zend_error(E_ERROR, "Cannot declare self-referencing constant '%s'", Z_STRVAL_P(p)); 480 } else if ((Z_TYPE_P(p) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) { 481 int refcount; 482 zend_uchar is_ref; 483 484 SEPARATE_ZVAL_IF_NOT_REF(pp); 485 p = *pp; 486 487 MARK_CONSTANT_VISITED(p); 488 489 refcount = Z_REFCOUNT_P(p); 490 is_ref = Z_ISREF_P(p); 491 492 if (!zend_get_constant_ex(p->value.str.val, p->value.str.len, &const_value, scope, Z_REAL_TYPE_P(p) TSRMLS_CC)) { 493 char *actual = Z_STRVAL_P(p); 494 495 if ((colon = (char*)zend_memrchr(Z_STRVAL_P(p), ':', Z_STRLEN_P(p)))) { 496 zend_error(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(p)); 497 Z_STRLEN_P(p) -= ((colon - Z_STRVAL_P(p)) + 1); 498 if (inline_change) { 499 colon = estrndup(colon, Z_STRLEN_P(p)); 500 str_efree(Z_STRVAL_P(p)); 501 Z_STRVAL_P(p) = colon; 502 } else { 503 Z_STRVAL_P(p) = colon + 1; 504 } 505 } else { 506 char *save = actual, *slash; 507 int actual_len = Z_STRLEN_P(p); 508 if ((Z_TYPE_P(p) & IS_CONSTANT_UNQUALIFIED) && (slash = (char *)zend_memrchr(actual, '\\', actual_len))) { 509 actual = slash + 1; 510 actual_len -= (actual - Z_STRVAL_P(p)); 511 if (inline_change) { 512 actual = estrndup(actual, actual_len); 513 Z_STRVAL_P(p) = actual; 514 Z_STRLEN_P(p) = actual_len; 515 } 516 } 517 if (actual[0] == '\\') { 518 if (inline_change) { 519 memmove(Z_STRVAL_P(p), Z_STRVAL_P(p)+1, Z_STRLEN_P(p)); 520 --Z_STRLEN_P(p); 521 } else { 522 ++actual; 523 } 524 --actual_len; 525 } 526 if ((Z_TYPE_P(p) & IS_CONSTANT_UNQUALIFIED) == 0) { 527 int fix_save = 0; 528 if (save[0] == '\\') { 529 save++; 530 fix_save = 1; 531 } 532 zend_error(E_ERROR, "Undefined constant '%s'", save); 533 if (fix_save) { 534 save--; 535 } 536 if (inline_change && !IS_INTERNED(save)) { 537 efree(save); 538 } 539 save = NULL; 540 } 541 if (inline_change && save && save != actual && !IS_INTERNED(save)) { 542 efree(save); 543 } 544 zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", actual, actual); 545 p->type = IS_STRING; 546 if (!inline_change) { 547 Z_STRVAL_P(p) = actual; 548 Z_STRLEN_P(p) = actual_len; 549 zval_copy_ctor(p); 550 } 551 } 552 } else { 553 if (inline_change) { 554 STR_FREE(Z_STRVAL_P(p)); 555 } 556 *p = const_value; 557 } 558 559 Z_SET_REFCOUNT_P(p, refcount); 560 Z_SET_ISREF_TO_P(p, is_ref); 561 } else if (Z_TYPE_P(p) == IS_CONSTANT_ARRAY) { 562 zval **element, *new_val; 563 char *str_index; 564 uint str_index_len; 565 ulong num_index; 566 int ret; 567 568 SEPARATE_ZVAL_IF_NOT_REF(pp); 569 p = *pp; 570 Z_TYPE_P(p) = IS_ARRAY; 571 572 if (!inline_change) { 573 zval *tmp; 574 HashTable *tmp_ht = NULL; 575 576 ALLOC_HASHTABLE(tmp_ht); 577 zend_hash_init(tmp_ht, zend_hash_num_elements(Z_ARRVAL_P(p)), NULL, ZVAL_PTR_DTOR, 0); 578 zend_hash_copy(tmp_ht, Z_ARRVAL_P(p), (copy_ctor_func_t) zval_deep_copy, (void *) &tmp, sizeof(zval *)); 579 Z_ARRVAL_P(p) = tmp_ht; 580 } 581 582 /* First go over the array and see if there are any constant indices */ 583 zend_hash_internal_pointer_reset(Z_ARRVAL_P(p)); 584 while (zend_hash_get_current_data(Z_ARRVAL_P(p), (void **) &element) == SUCCESS) { 585 if (!(Z_TYPE_PP(element) & IS_CONSTANT_INDEX)) { 586 zend_hash_move_forward(Z_ARRVAL_P(p)); 587 continue; 588 } 589 Z_TYPE_PP(element) &= ~IS_CONSTANT_INDEX; 590 if (zend_hash_get_current_key_ex(Z_ARRVAL_P(p), &str_index, &str_index_len, &num_index, 0, NULL) != HASH_KEY_IS_STRING) { 591 zend_hash_move_forward(Z_ARRVAL_P(p)); 592 continue; 593 } 594 if (!zend_get_constant_ex(str_index, str_index_len - 3, &const_value, scope, str_index[str_index_len - 2] TSRMLS_CC)) { 595 char *actual; 596 const char *save = str_index; 597 if ((colon = (char*)zend_memrchr(str_index, ':', str_index_len - 3))) { 598 zend_error(E_ERROR, "Undefined class constant '%s'", str_index); 599 str_index_len -= ((colon - str_index) + 1); 600 str_index = colon; 601 } else { 602 if (str_index[str_index_len - 2] & IS_CONSTANT_UNQUALIFIED) { 603 if ((actual = (char *)zend_memrchr(str_index, '\\', str_index_len - 3))) { 604 actual++; 605 str_index_len -= (actual - str_index); 606 str_index = actual; 607 } 608 } 609 if (str_index[0] == '\\') { 610 ++str_index; 611 --str_index_len; 612 } 613 if (save[0] == '\\') { 614 ++save; 615 } 616 if ((str_index[str_index_len - 2] & IS_CONSTANT_UNQUALIFIED) == 0) { 617 zend_error(E_ERROR, "Undefined constant '%s'", save); 618 } 619 zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", str_index, str_index); 620 } 621 ZVAL_STRINGL(&const_value, str_index, str_index_len-3, 1); 622 } 623 624 if (Z_REFCOUNT_PP(element) > 1) { 625 ALLOC_ZVAL(new_val); 626 *new_val = **element; 627 zval_copy_ctor(new_val); 628 Z_SET_REFCOUNT_P(new_val, 1); 629 Z_UNSET_ISREF_P(new_val); 630 631 /* preserve this bit for inheritance */ 632 Z_TYPE_PP(element) |= IS_CONSTANT_INDEX; 633 zval_ptr_dtor(element); 634 *element = new_val; 635 } 636 637 switch (Z_TYPE(const_value)) { 638 case IS_STRING: 639 ret = zend_symtable_update_current_key(Z_ARRVAL_P(p), Z_STRVAL(const_value), Z_STRLEN(const_value) + 1, HASH_UPDATE_KEY_IF_BEFORE); 640 break; 641 case IS_BOOL: 642 case IS_LONG: 643 ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL, 0, Z_LVAL(const_value), HASH_UPDATE_KEY_IF_BEFORE, NULL); 644 break; 645 case IS_DOUBLE: 646 ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL, 0, zend_dval_to_lval(Z_DVAL(const_value)), HASH_UPDATE_KEY_IF_BEFORE, NULL); 647 break; 648 case IS_NULL: 649 ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_STRING, "", 1, 0, HASH_UPDATE_KEY_IF_BEFORE, NULL); 650 break; 651 default: 652 ret = SUCCESS; 653 break; 654 } 655 if (ret == SUCCESS) { 656 zend_hash_move_forward(Z_ARRVAL_P(p)); 657 } 658 zval_dtor(&const_value); 659 } 660 zend_hash_apply_with_argument(Z_ARRVAL_P(p), (apply_func_arg_t) zval_update_constant_inline_change, (void *) scope TSRMLS_CC); 661 zend_hash_internal_pointer_reset(Z_ARRVAL_P(p)); 662 } 663 return 0; 664} 665/* }}} */ 666 667ZEND_API int zval_update_constant_inline_change(zval **pp, void *scope TSRMLS_DC) /* {{{ */ 668{ 669 return zval_update_constant_ex(pp, (void*)1, scope TSRMLS_CC); 670} 671/* }}} */ 672 673ZEND_API int zval_update_constant_no_inline_change(zval **pp, void *scope TSRMLS_DC) /* {{{ */ 674{ 675 return zval_update_constant_ex(pp, (void*)0, scope TSRMLS_CC); 676} 677/* }}} */ 678 679ZEND_API int zval_update_constant(zval **pp, void *arg TSRMLS_DC) /* {{{ */ 680{ 681 return zval_update_constant_ex(pp, arg, NULL TSRMLS_CC); 682} 683/* }}} */ 684 685int call_user_function(HashTable *function_table, zval **object_pp, zval *function_name, zval *retval_ptr, zend_uint param_count, zval *params[] TSRMLS_DC) /* {{{ */ 686{ 687 zval ***params_array; 688 zend_uint i; 689 int ex_retval; 690 zval *local_retval_ptr = NULL; 691 692 if (param_count) { 693 params_array = (zval ***) emalloc(sizeof(zval **)*param_count); 694 for (i=0; i<param_count; i++) { 695 params_array[i] = ¶ms[i]; 696 } 697 } else { 698 params_array = NULL; 699 } 700 ex_retval = call_user_function_ex(function_table, object_pp, function_name, &local_retval_ptr, param_count, params_array, 1, NULL TSRMLS_CC); 701 if (local_retval_ptr) { 702 COPY_PZVAL_TO_ZVAL(*retval_ptr, local_retval_ptr); 703 } else { 704 INIT_ZVAL(*retval_ptr); 705 } 706 if (params_array) { 707 efree(params_array); 708 } 709 return ex_retval; 710} 711/* }}} */ 712 713int call_user_function_ex(HashTable *function_table, zval **object_pp, zval *function_name, zval **retval_ptr_ptr, zend_uint param_count, zval **params[], int no_separation, HashTable *symbol_table TSRMLS_DC) /* {{{ */ 714{ 715 zend_fcall_info fci; 716 717 fci.size = sizeof(fci); 718 fci.function_table = function_table; 719 fci.object_ptr = object_pp ? *object_pp : NULL; 720 fci.function_name = function_name; 721 fci.retval_ptr_ptr = retval_ptr_ptr; 722 fci.param_count = param_count; 723 fci.params = params; 724 fci.no_separation = (zend_bool) no_separation; 725 fci.symbol_table = symbol_table; 726 727 return zend_call_function(&fci, NULL TSRMLS_CC); 728} 729/* }}} */ 730 731int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TSRMLS_DC) /* {{{ */ 732{ 733 zend_uint i; 734 zval **original_return_value; 735 HashTable *calling_symbol_table; 736 zend_op_array *original_op_array; 737 zend_op **original_opline_ptr; 738 zend_class_entry *current_scope; 739 zend_class_entry *current_called_scope; 740 zend_class_entry *calling_scope = NULL; 741 zend_class_entry *called_scope = NULL; 742 zval *current_this; 743 zend_execute_data execute_data; 744 zend_fcall_info_cache fci_cache_local; 745 746 *fci->retval_ptr_ptr = NULL; 747 748 if (!EG(active)) { 749 return FAILURE; /* executor is already inactive */ 750 } 751 752 if (EG(exception)) { 753 return FAILURE; /* we would result in an instable executor otherwise */ 754 } 755 756 switch (fci->size) { 757 case sizeof(zend_fcall_info): 758 break; /* nothing to do currently */ 759 default: 760 zend_error(E_ERROR, "Corrupted fcall_info provided to zend_call_function()"); 761 break; 762 } 763 764 /* Initialize execute_data */ 765 if (EG(current_execute_data)) { 766 execute_data = *EG(current_execute_data); 767 EX(op_array) = NULL; 768 EX(opline) = NULL; 769 EX(object) = NULL; 770 } else { 771 /* This only happens when we're called outside any execute()'s 772 * It shouldn't be strictly necessary to NULL execute_data out, 773 * but it may make bugs easier to spot 774 */ 775 memset(&execute_data, 0, sizeof(zend_execute_data)); 776 } 777 778 if (!fci_cache || !fci_cache->initialized) { 779 char *callable_name; 780 char *error = NULL; 781 782 if (!fci_cache) { 783 fci_cache = &fci_cache_local; 784 } 785 786 if (!zend_is_callable_ex(fci->function_name, fci->object_ptr, IS_CALLABLE_CHECK_SILENT, &callable_name, NULL, fci_cache, &error TSRMLS_CC)) { 787 if (error) { 788 zend_error(E_WARNING, "Invalid callback %s, %s", callable_name, error); 789 efree(error); 790 } 791 if (callable_name) { 792 efree(callable_name); 793 } 794 return FAILURE; 795 } else if (error) { 796 /* Capitalize the first latter of the error message */ 797 if (error[0] >= 'a' && error[0] <= 'z') { 798 error[0] += ('A' - 'a'); 799 } 800 zend_error(E_STRICT, "%s", error); 801 efree(error); 802 } 803 efree(callable_name); 804 } 805 806 EX(function_state).function = fci_cache->function_handler; 807 calling_scope = fci_cache->calling_scope; 808 called_scope = fci_cache->called_scope; 809 fci->object_ptr = fci_cache->object_ptr; 810 EX(object) = fci->object_ptr; 811 if (fci->object_ptr && Z_TYPE_P(fci->object_ptr) == IS_OBJECT && 812 (!EG(objects_store).object_buckets || !EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(fci->object_ptr)].valid)) { 813 return FAILURE; 814 } 815 816 if (EX(function_state).function->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) { 817 if (EX(function_state).function->common.fn_flags & ZEND_ACC_ABSTRACT) { 818 zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", EX(function_state).function->common.scope->name, EX(function_state).function->common.function_name); 819 } 820 if (EX(function_state).function->common.fn_flags & ZEND_ACC_DEPRECATED) { 821 zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated", 822 EX(function_state).function->common.scope ? EX(function_state).function->common.scope->name : "", 823 EX(function_state).function->common.scope ? "::" : "", 824 EX(function_state).function->common.function_name); 825 } 826 } 827 828 ZEND_VM_STACK_GROW_IF_NEEDED(fci->param_count + 1); 829 830 for (i=0; i<fci->param_count; i++) { 831 zval *param; 832 833 if (ARG_SHOULD_BE_SENT_BY_REF(EX(function_state).function, i + 1)) { 834 if (!PZVAL_IS_REF(*fci->params[i]) && Z_REFCOUNT_PP(fci->params[i]) > 1) { 835 zval *new_zval; 836 837 if (fci->no_separation && 838 !ARG_MAY_BE_SENT_BY_REF(EX(function_state).function, i + 1)) { 839 if (i || UNEXPECTED(ZEND_VM_STACK_ELEMETS(EG(argument_stack)) == (EG(argument_stack)->top))) { 840 /* hack to clean up the stack */ 841 zend_vm_stack_push((void *) (zend_uintptr_t)i TSRMLS_CC); 842 zend_vm_stack_clear_multiple(0 TSRMLS_CC); 843 } 844 845 zend_error(E_WARNING, "Parameter %d to %s%s%s() expected to be a reference, value given", 846 i+1, 847 EX(function_state).function->common.scope ? EX(function_state).function->common.scope->name : "", 848 EX(function_state).function->common.scope ? "::" : "", 849 EX(function_state).function->common.function_name); 850 return FAILURE; 851 } 852 853 ALLOC_ZVAL(new_zval); 854 *new_zval = **fci->params[i]; 855 zval_copy_ctor(new_zval); 856 Z_SET_REFCOUNT_P(new_zval, 1); 857 Z_DELREF_PP(fci->params[i]); 858 *fci->params[i] = new_zval; 859 } 860 Z_ADDREF_PP(fci->params[i]); 861 Z_SET_ISREF_PP(fci->params[i]); 862 param = *fci->params[i]; 863 } else if (PZVAL_IS_REF(*fci->params[i]) && 864 /* don't separate references for __call */ 865 (EX(function_state).function->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0 ) { 866 ALLOC_ZVAL(param); 867 *param = **(fci->params[i]); 868 INIT_PZVAL(param); 869 zval_copy_ctor(param); 870 } else if (*fci->params[i] != &EG(uninitialized_zval)) { 871 Z_ADDREF_PP(fci->params[i]); 872 param = *fci->params[i]; 873 } else { 874 ALLOC_ZVAL(param); 875 *param = **(fci->params[i]); 876 INIT_PZVAL(param); 877 } 878 zend_vm_stack_push(param TSRMLS_CC); 879 } 880 881 EX(function_state).arguments = zend_vm_stack_top(TSRMLS_C); 882 zend_vm_stack_push((void*)(zend_uintptr_t)fci->param_count TSRMLS_CC); 883 884 current_scope = EG(scope); 885 EG(scope) = calling_scope; 886 887 current_this = EG(This); 888 889 current_called_scope = EG(called_scope); 890 if (called_scope) { 891 EG(called_scope) = called_scope; 892 } else if (EX(function_state).function->type != ZEND_INTERNAL_FUNCTION) { 893 EG(called_scope) = NULL; 894 } 895 896 if (fci->object_ptr) { 897 if ((EX(function_state).function->common.fn_flags & ZEND_ACC_STATIC)) { 898 EG(This) = NULL; 899 } else { 900 EG(This) = fci->object_ptr; 901 902 if (!PZVAL_IS_REF(EG(This))) { 903 Z_ADDREF_P(EG(This)); /* For $this pointer */ 904 } else { 905 zval *this_ptr; 906 907 ALLOC_ZVAL(this_ptr); 908 *this_ptr = *EG(This); 909 INIT_PZVAL(this_ptr); 910 zval_copy_ctor(this_ptr); 911 EG(This) = this_ptr; 912 } 913 } 914 } else { 915 EG(This) = NULL; 916 } 917 918 EX(prev_execute_data) = EG(current_execute_data); 919 EG(current_execute_data) = &execute_data; 920 921 if (EX(function_state).function->type == ZEND_USER_FUNCTION) { 922 calling_symbol_table = EG(active_symbol_table); 923 EG(scope) = EX(function_state).function->common.scope; 924 if (fci->symbol_table) { 925 EG(active_symbol_table) = fci->symbol_table; 926 } else { 927 EG(active_symbol_table) = NULL; 928 } 929 930 original_return_value = EG(return_value_ptr_ptr); 931 original_op_array = EG(active_op_array); 932 EG(return_value_ptr_ptr) = fci->retval_ptr_ptr; 933 EG(active_op_array) = (zend_op_array *) EX(function_state).function; 934 original_opline_ptr = EG(opline_ptr); 935 936 if (EG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) { 937 *fci->retval_ptr_ptr = zend_generator_create_zval(EG(active_op_array) TSRMLS_CC); 938 } else { 939 zend_execute(EG(active_op_array) TSRMLS_CC); 940 } 941 942 if (!fci->symbol_table && EG(active_symbol_table)) { 943 zend_clean_and_cache_symbol_table(EG(active_symbol_table) TSRMLS_CC); 944 } 945 EG(active_symbol_table) = calling_symbol_table; 946 EG(active_op_array) = original_op_array; 947 EG(return_value_ptr_ptr)=original_return_value; 948 EG(opline_ptr) = original_opline_ptr; 949 } else if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION) { 950 int call_via_handler = (EX(function_state).function->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0; 951 ALLOC_INIT_ZVAL(*fci->retval_ptr_ptr); 952 if (EX(function_state).function->common.scope) { 953 EG(scope) = EX(function_state).function->common.scope; 954 } 955 if(EXPECTED(zend_execute_internal == NULL)) { 956 /* saves one function call if zend_execute_internal is not used */ 957 ((zend_internal_function *) EX(function_state).function)->handler(fci->param_count, *fci->retval_ptr_ptr, fci->retval_ptr_ptr, fci->object_ptr, 1 TSRMLS_CC); 958 } else { 959 zend_execute_internal(&execute_data, fci, 1 TSRMLS_CC); 960 } 961 /* We shouldn't fix bad extensions here, 962 because it can break proper ones (Bug #34045) 963 if (!EX(function_state).function->common.return_reference) 964 { 965 INIT_PZVAL(*fci->retval_ptr_ptr); 966 }*/ 967 if (EG(exception) && fci->retval_ptr_ptr) { 968 zval_ptr_dtor(fci->retval_ptr_ptr); 969 *fci->retval_ptr_ptr = NULL; 970 } 971 972 if (call_via_handler) { 973 /* We must re-initialize function again */ 974 fci_cache->initialized = 0; 975 } 976 } else { /* ZEND_OVERLOADED_FUNCTION */ 977 ALLOC_INIT_ZVAL(*fci->retval_ptr_ptr); 978 979 /* Not sure what should be done here if it's a static method */ 980 if (fci->object_ptr) { 981 Z_OBJ_HT_P(fci->object_ptr)->call_method(EX(function_state).function->common.function_name, fci->param_count, *fci->retval_ptr_ptr, fci->retval_ptr_ptr, fci->object_ptr, 1 TSRMLS_CC); 982 } else { 983 zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object"); 984 } 985 986 if (EX(function_state).function->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) { 987 efree((char*)EX(function_state).function->common.function_name); 988 } 989 efree(EX(function_state).function); 990 991 if (EG(exception) && fci->retval_ptr_ptr) { 992 zval_ptr_dtor(fci->retval_ptr_ptr); 993 *fci->retval_ptr_ptr = NULL; 994 } 995 } 996 zend_vm_stack_clear_multiple(0 TSRMLS_CC); 997 998 if (EG(This)) { 999 zval_ptr_dtor(&EG(This)); 1000 } 1001 EG(called_scope) = current_called_scope; 1002 EG(scope) = current_scope; 1003 EG(This) = current_this; 1004 EG(current_execute_data) = EX(prev_execute_data); 1005 1006 if (EG(exception)) { 1007 zend_throw_exception_internal(NULL TSRMLS_CC); 1008 } 1009 return SUCCESS; 1010} 1011/* }}} */ 1012 1013ZEND_API int zend_lookup_class_ex(const char *name, int name_length, const zend_literal *key, int use_autoload, zend_class_entry ***ce TSRMLS_DC) /* {{{ */ 1014{ 1015 zval **args[1]; 1016 zval autoload_function; 1017 zval *class_name_ptr; 1018 zval *retval_ptr = NULL; 1019 int retval, lc_length; 1020 char *lc_name; 1021 char *lc_free; 1022 zend_fcall_info fcall_info; 1023 zend_fcall_info_cache fcall_cache; 1024 char dummy = 1; 1025 ulong hash; 1026 ALLOCA_FLAG(use_heap) 1027 1028 if (key) { 1029 lc_name = Z_STRVAL(key->constant); 1030 lc_length = Z_STRLEN(key->constant) + 1; 1031 hash = key->hash_value; 1032 } else { 1033 if (name == NULL || !name_length) { 1034 return FAILURE; 1035 } 1036 1037 lc_free = lc_name = do_alloca(name_length + 1, use_heap); 1038 zend_str_tolower_copy(lc_name, name, name_length); 1039 lc_length = name_length + 1; 1040 1041 if (lc_name[0] == '\\') { 1042 lc_name += 1; 1043 lc_length -= 1; 1044 } 1045 1046 hash = zend_inline_hash_func(lc_name, lc_length); 1047 } 1048 1049 if (zend_hash_quick_find(EG(class_table), lc_name, lc_length, hash, (void **) ce) == SUCCESS) { 1050 if (!key) { 1051 free_alloca(lc_free, use_heap); 1052 } 1053 return SUCCESS; 1054 } 1055 1056 /* The compiler is not-reentrant. Make sure we __autoload() only during run-time 1057 * (doesn't impact fuctionality of __autoload() 1058 */ 1059 if (!use_autoload || zend_is_compiling(TSRMLS_C)) { 1060 if (!key) { 1061 free_alloca(lc_free, use_heap); 1062 } 1063 return FAILURE; 1064 } 1065 1066 if (EG(in_autoload) == NULL) { 1067 ALLOC_HASHTABLE(EG(in_autoload)); 1068 zend_hash_init(EG(in_autoload), 0, NULL, NULL, 0); 1069 } 1070 1071 if (zend_hash_quick_add(EG(in_autoload), lc_name, lc_length, hash, (void**)&dummy, sizeof(char), NULL) == FAILURE) { 1072 if (!key) { 1073 free_alloca(lc_free, use_heap); 1074 } 1075 return FAILURE; 1076 } 1077 1078 ZVAL_STRINGL(&autoload_function, ZEND_AUTOLOAD_FUNC_NAME, sizeof(ZEND_AUTOLOAD_FUNC_NAME) - 1, 0); 1079 1080 ALLOC_ZVAL(class_name_ptr); 1081 INIT_PZVAL(class_name_ptr); 1082 if (name[0] == '\\') { 1083 ZVAL_STRINGL(class_name_ptr, name+1, name_length-1, 1); 1084 } else { 1085 ZVAL_STRINGL(class_name_ptr, name, name_length, 1); 1086 } 1087 1088 args[0] = &class_name_ptr; 1089 1090 fcall_info.size = sizeof(fcall_info); 1091 fcall_info.function_table = EG(function_table); 1092 fcall_info.function_name = &autoload_function; 1093 fcall_info.symbol_table = NULL; 1094 fcall_info.retval_ptr_ptr = &retval_ptr; 1095 fcall_info.param_count = 1; 1096 fcall_info.params = args; 1097 fcall_info.object_ptr = NULL; 1098 fcall_info.no_separation = 1; 1099 1100 fcall_cache.initialized = EG(autoload_func) ? 1 : 0; 1101 fcall_cache.function_handler = EG(autoload_func); 1102 fcall_cache.calling_scope = NULL; 1103 fcall_cache.called_scope = NULL; 1104 fcall_cache.object_ptr = NULL; 1105 1106 zend_exception_save(TSRMLS_C); 1107 retval = zend_call_function(&fcall_info, &fcall_cache TSRMLS_CC); 1108 zend_exception_restore(TSRMLS_C); 1109 1110 EG(autoload_func) = fcall_cache.function_handler; 1111 1112 zval_ptr_dtor(&class_name_ptr); 1113 1114 zend_hash_quick_del(EG(in_autoload), lc_name, lc_length, hash); 1115 1116 if (retval_ptr) { 1117 zval_ptr_dtor(&retval_ptr); 1118 } 1119 1120 if (retval == SUCCESS) { 1121 retval = zend_hash_quick_find(EG(class_table), lc_name, lc_length, hash, (void **) ce); 1122 } 1123 if (!key) { 1124 free_alloca(lc_free, use_heap); 1125 } 1126 return retval; 1127} 1128/* }}} */ 1129 1130ZEND_API int zend_lookup_class(const char *name, int name_length, zend_class_entry ***ce TSRMLS_DC) /* {{{ */ 1131{ 1132 return zend_lookup_class_ex(name, name_length, NULL, 1, ce TSRMLS_CC); 1133} 1134/* }}} */ 1135 1136ZEND_API int zend_eval_stringl(char *str, int str_len, zval *retval_ptr, char *string_name TSRMLS_DC) /* {{{ */ 1137{ 1138 zval pv; 1139 zend_op_array *new_op_array; 1140 zend_op_array *original_active_op_array = EG(active_op_array); 1141 zend_uint original_compiler_options; 1142 int retval; 1143 1144 if (retval_ptr) { 1145 Z_STRLEN(pv) = str_len + sizeof("return ;") - 1; 1146 Z_STRVAL(pv) = emalloc(Z_STRLEN(pv) + 1); 1147 memcpy(Z_STRVAL(pv), "return ", sizeof("return ") - 1); 1148 memcpy(Z_STRVAL(pv) + sizeof("return ") - 1, str, str_len); 1149 Z_STRVAL(pv)[Z_STRLEN(pv) - 1] = ';'; 1150 Z_STRVAL(pv)[Z_STRLEN(pv)] = '\0'; 1151 } else { 1152 Z_STRLEN(pv) = str_len; 1153 Z_STRVAL(pv) = str; 1154 } 1155 Z_TYPE(pv) = IS_STRING; 1156 1157 /*printf("Evaluating '%s'\n", pv.value.str.val);*/ 1158 1159 original_compiler_options = CG(compiler_options); 1160 CG(compiler_options) = ZEND_COMPILE_DEFAULT_FOR_EVAL; 1161 new_op_array = zend_compile_string(&pv, string_name TSRMLS_CC); 1162 CG(compiler_options) = original_compiler_options; 1163 1164 if (new_op_array) { 1165 zval *local_retval_ptr=NULL; 1166 zval **original_return_value_ptr_ptr = EG(return_value_ptr_ptr); 1167 zend_op **original_opline_ptr = EG(opline_ptr); 1168 int orig_interactive = CG(interactive); 1169 1170 EG(return_value_ptr_ptr) = &local_retval_ptr; 1171 EG(active_op_array) = new_op_array; 1172 EG(no_extensions)=1; 1173 if (!EG(active_symbol_table)) { 1174 zend_rebuild_symbol_table(TSRMLS_C); 1175 } 1176 CG(interactive) = 0; 1177 1178 zend_try { 1179 zend_execute(new_op_array TSRMLS_CC); 1180 } zend_catch { 1181 destroy_op_array(new_op_array TSRMLS_CC); 1182 efree(new_op_array); 1183 zend_bailout(); 1184 } zend_end_try(); 1185 1186 CG(interactive) = orig_interactive; 1187 if (local_retval_ptr) { 1188 if (retval_ptr) { 1189 COPY_PZVAL_TO_ZVAL(*retval_ptr, local_retval_ptr); 1190 } else { 1191 zval_ptr_dtor(&local_retval_ptr); 1192 } 1193 } else { 1194 if (retval_ptr) { 1195 INIT_ZVAL(*retval_ptr); 1196 } 1197 } 1198 1199 EG(no_extensions)=0; 1200 EG(opline_ptr) = original_opline_ptr; 1201 EG(active_op_array) = original_active_op_array; 1202 destroy_op_array(new_op_array TSRMLS_CC); 1203 efree(new_op_array); 1204 EG(return_value_ptr_ptr) = original_return_value_ptr_ptr; 1205 retval = SUCCESS; 1206 } else { 1207 retval = FAILURE; 1208 } 1209 if (retval_ptr) { 1210 zval_dtor(&pv); 1211 } 1212 return retval; 1213} 1214/* }}} */ 1215 1216ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSRMLS_DC) /* {{{ */ 1217{ 1218 return zend_eval_stringl(str, strlen(str), retval_ptr, string_name TSRMLS_CC); 1219} 1220/* }}} */ 1221 1222ZEND_API int zend_eval_stringl_ex(char *str, int str_len, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC) /* {{{ */ 1223{ 1224 int result; 1225 1226 result = zend_eval_stringl(str, str_len, retval_ptr, string_name TSRMLS_CC); 1227 if (handle_exceptions && EG(exception)) { 1228 zend_exception_error(EG(exception), E_ERROR TSRMLS_CC); 1229 result = FAILURE; 1230 } 1231 return result; 1232} 1233/* }}} */ 1234 1235ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC) /* {{{ */ 1236{ 1237 return zend_eval_stringl_ex(str, strlen(str), retval_ptr, string_name, handle_exceptions TSRMLS_CC); 1238} 1239/* }}} */ 1240 1241void execute_new_code(TSRMLS_D) /* {{{ */ 1242{ 1243 zend_op *opline, *end; 1244 zend_op *ret_opline; 1245 int orig_interactive; 1246 1247 if (!(CG(active_op_array)->fn_flags & ZEND_ACC_INTERACTIVE) 1248 || CG(context).backpatch_count>0 1249 || CG(active_op_array)->function_name 1250 || CG(active_op_array)->type!=ZEND_USER_FUNCTION) { 1251 return; 1252 } 1253 1254 ret_opline = get_next_op(CG(active_op_array) TSRMLS_CC); 1255 ret_opline->opcode = ZEND_RETURN; 1256 ret_opline->op1_type = IS_CONST; 1257 ret_opline->op1.constant = zend_add_literal(CG(active_op_array), &EG(uninitialized_zval) TSRMLS_CC); 1258 SET_UNUSED(ret_opline->op2); 1259 1260 if (!EG(start_op)) { 1261 EG(start_op) = CG(active_op_array)->opcodes; 1262 } 1263 1264 opline=EG(start_op); 1265 end=CG(active_op_array)->opcodes+CG(active_op_array)->last; 1266 1267 while (opline<end) { 1268 if (opline->op1_type == IS_CONST) { 1269 opline->op1.zv = &CG(active_op_array)->literals[opline->op1.constant].constant; 1270 } 1271 if (opline->op2_type == IS_CONST) { 1272 opline->op2.zv = &CG(active_op_array)->literals[opline->op2.constant].constant; 1273 } 1274 switch (opline->opcode) { 1275 case ZEND_GOTO: 1276 if (Z_TYPE_P(opline->op2.zv) != IS_LONG) { 1277 zend_resolve_goto_label(CG(active_op_array), opline, 1 TSRMLS_CC); 1278 } 1279 /* break omitted intentionally */ 1280 case ZEND_JMP: 1281 opline->op1.jmp_addr = &CG(active_op_array)->opcodes[opline->op1.opline_num]; 1282 break; 1283 case ZEND_JMPZ: 1284 case ZEND_JMPNZ: 1285 case ZEND_JMPZ_EX: 1286 case ZEND_JMPNZ_EX: 1287 case ZEND_JMP_SET: 1288 case ZEND_JMP_SET_VAR: 1289 opline->op2.jmp_addr = &CG(active_op_array)->opcodes[opline->op2.opline_num]; 1290 break; 1291 } 1292 ZEND_VM_SET_OPCODE_HANDLER(opline); 1293 opline++; 1294 } 1295 1296 zend_release_labels(1 TSRMLS_CC); 1297 1298 EG(return_value_ptr_ptr) = NULL; 1299 EG(active_op_array) = CG(active_op_array); 1300 orig_interactive = CG(interactive); 1301 CG(interactive) = 0; 1302 zend_execute(CG(active_op_array) TSRMLS_CC); 1303 CG(interactive) = orig_interactive; 1304 1305 if (EG(exception)) { 1306 zend_exception_error(EG(exception), E_ERROR TSRMLS_CC); 1307 } 1308 1309 CG(active_op_array)->last -= 1; /* get rid of that ZEND_RETURN */ 1310 EG(start_op) = CG(active_op_array)->opcodes+CG(active_op_array)->last; 1311} 1312/* }}} */ 1313 1314ZEND_API void zend_timeout(int dummy) /* {{{ */ 1315{ 1316 TSRMLS_FETCH(); 1317 1318 if (zend_on_timeout) { 1319#ifdef ZEND_SIGNALS 1320 /* 1321 We got here because we got a timeout signal, so we are in a signal handler 1322 at this point. However, we want to be able to timeout any user-supplied 1323 shutdown functions, so pretend we are not in a signal handler while we are 1324 calling these 1325 */ 1326 SIGG(running) = 0; 1327#endif 1328 zend_on_timeout(EG(timeout_seconds) TSRMLS_CC); 1329 } 1330 1331 zend_error(E_ERROR, "Maximum execution time of %d second%s exceeded", EG(timeout_seconds), EG(timeout_seconds) == 1 ? "" : "s"); 1332} 1333/* }}} */ 1334 1335#ifdef ZEND_WIN32 1336static LRESULT CALLBACK zend_timeout_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) /* {{{ */ 1337{ 1338 switch (message) { 1339 case WM_DESTROY: 1340 PostQuitMessage(0); 1341 break; 1342 case WM_REGISTER_ZEND_TIMEOUT: 1343 /* wParam is the thread id pointer, lParam is the timeout amount in seconds */ 1344 if (lParam == 0) { 1345 KillTimer(timeout_window, wParam); 1346 } else { 1347#ifdef ZTS 1348 void ***tsrm_ls; 1349#endif 1350 SetTimer(timeout_window, wParam, lParam*1000, NULL); 1351#ifdef ZTS 1352 tsrm_ls = ts_resource_ex(0, &wParam); 1353 if (!tsrm_ls) { 1354 /* shouldn't normally happen */ 1355 break; 1356 } 1357#endif 1358 EG(timed_out) = 0; 1359 } 1360 break; 1361 case WM_UNREGISTER_ZEND_TIMEOUT: 1362 /* wParam is the thread id pointer */ 1363 KillTimer(timeout_window, wParam); 1364 break; 1365 case WM_TIMER: { 1366#ifdef ZTS 1367 void ***tsrm_ls; 1368 1369 tsrm_ls = ts_resource_ex(0, &wParam); 1370 if (!tsrm_ls) { 1371 /* Thread died before receiving its timeout? */ 1372 break; 1373 } 1374#endif 1375 KillTimer(timeout_window, wParam); 1376 EG(timed_out) = 1; 1377 } 1378 break; 1379 default: 1380 return DefWindowProc(hWnd, message, wParam, lParam); 1381 } 1382 return 0; 1383} 1384/* }}} */ 1385 1386static unsigned __stdcall timeout_thread_proc(void *pArgs) /* {{{ */ 1387{ 1388 MSG message; 1389 1390 wc.style=0; 1391 wc.lpfnWndProc = zend_timeout_WndProc; 1392 wc.cbClsExtra=0; 1393 wc.cbWndExtra=0; 1394 wc.hInstance=NULL; 1395 wc.hIcon=NULL; 1396 wc.hCursor=NULL; 1397 wc.hbrBackground=(HBRUSH)(COLOR_BACKGROUND + 5); 1398 wc.lpszMenuName=NULL; 1399 wc.lpszClassName = "Zend Timeout Window"; 1400 if (!RegisterClass(&wc)) { 1401 return -1; 1402 } 1403 timeout_window = CreateWindow(wc.lpszClassName, wc.lpszClassName, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, NULL); 1404 SetEvent(timeout_thread_event); 1405 while (GetMessage(&message, NULL, 0, 0)) { 1406 SendMessage(timeout_window, message.message, message.wParam, message.lParam); 1407 if (message.message == WM_QUIT) { 1408 break; 1409 } 1410 } 1411 DestroyWindow(timeout_window); 1412 UnregisterClass(wc.lpszClassName, NULL); 1413 SetEvent(timeout_thread_handle); 1414 return 0; 1415} 1416/* }}} */ 1417 1418void zend_init_timeout_thread(void) /* {{{ */ 1419{ 1420 timeout_thread_event = CreateEvent(NULL, FALSE, FALSE, NULL); 1421 timeout_thread_handle = CreateEvent(NULL, FALSE, FALSE, NULL); 1422 _beginthreadex(NULL, 0, timeout_thread_proc, NULL, 0, &timeout_thread_id); 1423 WaitForSingleObject(timeout_thread_event, INFINITE); 1424} 1425/* }}} */ 1426 1427void zend_shutdown_timeout_thread(void) /* {{{ */ 1428{ 1429 if (!timeout_thread_initialized) { 1430 return; 1431 } 1432 PostThreadMessage(timeout_thread_id, WM_QUIT, 0, 0); 1433 1434 /* Wait for thread termination */ 1435 WaitForSingleObject(timeout_thread_handle, 5000); 1436 CloseHandle(timeout_thread_handle); 1437 timeout_thread_initialized = 0; 1438} 1439/* }}} */ 1440 1441#endif 1442 1443/* This one doesn't exists on QNX */ 1444#ifndef SIGPROF 1445#define SIGPROF 27 1446#endif 1447 1448void zend_set_timeout(long seconds, int reset_signals) /* {{{ */ 1449{ 1450 TSRMLS_FETCH(); 1451 1452 EG(timeout_seconds) = seconds; 1453 1454#ifdef ZEND_WIN32 1455 if(!seconds) { 1456 return; 1457 } 1458 if (timeout_thread_initialized == 0 && InterlockedIncrement(&timeout_thread_initialized) == 1) { 1459 /* We start up this process-wide thread here and not in zend_startup(), because if Zend 1460 * is initialized inside a DllMain(), you're not supposed to start threads from it. 1461 */ 1462 zend_init_timeout_thread(); 1463 } 1464 PostThreadMessage(timeout_thread_id, WM_REGISTER_ZEND_TIMEOUT, (WPARAM) GetCurrentThreadId(), (LPARAM) seconds); 1465#else 1466# ifdef HAVE_SETITIMER 1467 { 1468 struct itimerval t_r; /* timeout requested */ 1469 int signo; 1470 1471 if(seconds) { 1472 t_r.it_value.tv_sec = seconds; 1473 t_r.it_value.tv_usec = t_r.it_interval.tv_sec = t_r.it_interval.tv_usec = 0; 1474 1475# ifdef __CYGWIN__ 1476 setitimer(ITIMER_REAL, &t_r, NULL); 1477 } 1478 signo = SIGALRM; 1479# else 1480 setitimer(ITIMER_PROF, &t_r, NULL); 1481 } 1482 signo = SIGPROF; 1483# endif 1484 1485 if (reset_signals) { 1486# ifdef ZEND_SIGNALS 1487 zend_signal(signo, zend_timeout TSRMLS_CC); 1488# else 1489 sigset_t sigset; 1490 1491 signal(signo, zend_timeout); 1492 sigemptyset(&sigset); 1493 sigaddset(&sigset, signo); 1494 sigprocmask(SIG_UNBLOCK, &sigset, NULL); 1495# endif 1496 } 1497 } 1498# endif /* HAVE_SETITIMER */ 1499#endif 1500} 1501/* }}} */ 1502 1503void zend_unset_timeout(TSRMLS_D) /* {{{ */ 1504{ 1505#ifdef ZEND_WIN32 1506 if(timeout_thread_initialized) { 1507 PostThreadMessage(timeout_thread_id, WM_UNREGISTER_ZEND_TIMEOUT, (WPARAM) GetCurrentThreadId(), (LPARAM) 0); 1508 } 1509#else 1510# ifdef HAVE_SETITIMER 1511 if (EG(timeout_seconds)) { 1512 struct itimerval no_timeout; 1513 1514 no_timeout.it_value.tv_sec = no_timeout.it_value.tv_usec = no_timeout.it_interval.tv_sec = no_timeout.it_interval.tv_usec = 0; 1515 1516#ifdef __CYGWIN__ 1517 setitimer(ITIMER_REAL, &no_timeout, NULL); 1518#else 1519 setitimer(ITIMER_PROF, &no_timeout, NULL); 1520#endif 1521 } 1522# endif 1523#endif 1524} 1525/* }}} */ 1526 1527zend_class_entry *zend_fetch_class(const char *class_name, uint class_name_len, int fetch_type TSRMLS_DC) /* {{{ */ 1528{ 1529 zend_class_entry **pce; 1530 int use_autoload = (fetch_type & ZEND_FETCH_CLASS_NO_AUTOLOAD) == 0; 1531 int silent = (fetch_type & ZEND_FETCH_CLASS_SILENT) != 0; 1532 1533 fetch_type &= ZEND_FETCH_CLASS_MASK; 1534 1535check_fetch_type: 1536 switch (fetch_type) { 1537 case ZEND_FETCH_CLASS_SELF: 1538 if (!EG(scope)) { 1539 zend_error(E_ERROR, "Cannot access self:: when no class scope is active"); 1540 } 1541 return EG(scope); 1542 case ZEND_FETCH_CLASS_PARENT: 1543 if (!EG(scope)) { 1544 zend_error(E_ERROR, "Cannot access parent:: when no class scope is active"); 1545 } 1546 if (!EG(scope)->parent) { 1547 zend_error(E_ERROR, "Cannot access parent:: when current class scope has no parent"); 1548 } 1549 return EG(scope)->parent; 1550 case ZEND_FETCH_CLASS_STATIC: 1551 if (!EG(called_scope)) { 1552 zend_error(E_ERROR, "Cannot access static:: when no class scope is active"); 1553 } 1554 return EG(called_scope); 1555 case ZEND_FETCH_CLASS_AUTO: { 1556 fetch_type = zend_get_class_fetch_type(class_name, class_name_len); 1557 if (fetch_type!=ZEND_FETCH_CLASS_DEFAULT) { 1558 goto check_fetch_type; 1559 } 1560 } 1561 break; 1562 } 1563 1564 if (zend_lookup_class_ex(class_name, class_name_len, NULL, use_autoload, &pce TSRMLS_CC) == FAILURE) { 1565 if (use_autoload) { 1566 if (!silent && !EG(exception)) { 1567 if (fetch_type == ZEND_FETCH_CLASS_INTERFACE) { 1568 zend_error(E_ERROR, "Interface '%s' not found", class_name); 1569 } else if (fetch_type == ZEND_FETCH_CLASS_TRAIT) { 1570 zend_error(E_ERROR, "Trait '%s' not found", class_name); 1571 } else { 1572 zend_error(E_ERROR, "Class '%s' not found", class_name); 1573 } 1574 } 1575 } 1576 return NULL; 1577 } 1578 return *pce; 1579} 1580/* }}} */ 1581 1582zend_class_entry *zend_fetch_class_by_name(const char *class_name, uint class_name_len, const zend_literal *key, int fetch_type TSRMLS_DC) /* {{{ */ 1583{ 1584 zend_class_entry **pce; 1585 int use_autoload = (fetch_type & ZEND_FETCH_CLASS_NO_AUTOLOAD) == 0; 1586 1587 if (zend_lookup_class_ex(class_name, class_name_len, key, use_autoload, &pce TSRMLS_CC) == FAILURE) { 1588 if (use_autoload) { 1589 if ((fetch_type & ZEND_FETCH_CLASS_SILENT) == 0 && !EG(exception)) { 1590 if ((fetch_type & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_INTERFACE) { 1591 zend_error(E_ERROR, "Interface '%s' not found", class_name); 1592 } else if ((fetch_type & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_TRAIT) { 1593 zend_error(E_ERROR, "Trait '%s' not found", class_name); 1594 } else { 1595 zend_error(E_ERROR, "Class '%s' not found", class_name); 1596 } 1597 } 1598 } 1599 return NULL; 1600 } 1601 return *pce; 1602} 1603/* }}} */ 1604 1605#define MAX_ABSTRACT_INFO_CNT 3 1606#define MAX_ABSTRACT_INFO_FMT "%s%s%s%s" 1607#define DISPLAY_ABSTRACT_FN(idx) \ 1608 ai.afn[idx] ? ZEND_FN_SCOPE_NAME(ai.afn[idx]) : "", \ 1609 ai.afn[idx] ? "::" : "", \ 1610 ai.afn[idx] ? ai.afn[idx]->common.function_name : "", \ 1611 ai.afn[idx] && ai.afn[idx + 1] ? ", " : (ai.afn[idx] && ai.cnt > MAX_ABSTRACT_INFO_CNT ? ", ..." : "") 1612 1613typedef struct _zend_abstract_info { 1614 zend_function *afn[MAX_ABSTRACT_INFO_CNT + 1]; 1615 int cnt; 1616 int ctor; 1617} zend_abstract_info; 1618 1619static int zend_verify_abstract_class_function(zend_function *fn, zend_abstract_info *ai TSRMLS_DC) /* {{{ */ 1620{ 1621 if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) { 1622 if (ai->cnt < MAX_ABSTRACT_INFO_CNT) { 1623 ai->afn[ai->cnt] = fn; 1624 } 1625 if (fn->common.fn_flags & ZEND_ACC_CTOR) { 1626 if (!ai->ctor) { 1627 ai->cnt++; 1628 ai->ctor = 1; 1629 } else { 1630 ai->afn[ai->cnt] = NULL; 1631 } 1632 } else { 1633 ai->cnt++; 1634 } 1635 } 1636 return 0; 1637} 1638/* }}} */ 1639 1640void zend_verify_abstract_class(zend_class_entry *ce TSRMLS_DC) /* {{{ */ 1641{ 1642 zend_abstract_info ai; 1643 1644 if ((ce->ce_flags & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS) && !(ce->ce_flags & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) { 1645 memset(&ai, 0, sizeof(ai)); 1646 1647 zend_hash_apply_with_argument(&ce->function_table, (apply_func_arg_t) zend_verify_abstract_class_function, &ai TSRMLS_CC); 1648 1649 if (ai.cnt) { 1650 zend_error(E_ERROR, "Class %s contains %d abstract method%s and must therefore be declared abstract or implement the remaining methods (" MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT ")", 1651 ce->name, ai.cnt, 1652 ai.cnt > 1 ? "s" : "", 1653 DISPLAY_ABSTRACT_FN(0), 1654 DISPLAY_ABSTRACT_FN(1), 1655 DISPLAY_ABSTRACT_FN(2) 1656 ); 1657 } 1658 } 1659} 1660/* }}} */ 1661 1662ZEND_API void zend_reset_all_cv(HashTable *symbol_table TSRMLS_DC) /* {{{ */ 1663{ 1664 zend_execute_data *ex; 1665 int i; 1666 1667 for (ex = EG(current_execute_data); ex; ex = ex->prev_execute_data) { 1668 if (ex->op_array && ex->symbol_table == symbol_table) { 1669 for (i = 0; i < ex->op_array->last_var; i++) { 1670 *EX_CV_NUM(ex, i) = NULL; 1671 } 1672 } 1673 } 1674} 1675/* }}} */ 1676 1677ZEND_API void zend_delete_variable(zend_execute_data *ex, HashTable *ht, const char *name, int name_len, ulong hash_value TSRMLS_DC) /* {{{ */ 1678{ 1679 if (zend_hash_quick_del(ht, name, name_len, hash_value) == SUCCESS) { 1680 name_len--; 1681 while (ex && ex->symbol_table == ht) { 1682 int i; 1683 1684 if (ex->op_array) { 1685 for (i = 0; i < ex->op_array->last_var; i++) { 1686 if (ex->op_array->vars[i].hash_value == hash_value && 1687 ex->op_array->vars[i].name_len == name_len && 1688 !memcmp(ex->op_array->vars[i].name, name, name_len)) { 1689 *EX_CV_NUM(ex, i) = NULL; 1690 break; 1691 } 1692 } 1693 } 1694 ex = ex->prev_execute_data; 1695 } 1696 } 1697} 1698/* }}} */ 1699 1700ZEND_API int zend_delete_global_variable_ex(const char *name, int name_len, ulong hash_value TSRMLS_DC) /* {{{ */ 1701{ 1702 zend_execute_data *ex; 1703 1704 if (zend_hash_quick_exists(&EG(symbol_table), name, name_len + 1, hash_value)) { 1705 for (ex = EG(current_execute_data); ex; ex = ex->prev_execute_data) { 1706 if (ex->op_array && ex->symbol_table == &EG(symbol_table)) { 1707 int i; 1708 for (i = 0; i < ex->op_array->last_var; i++) { 1709 if (ex->op_array->vars[i].hash_value == hash_value && 1710 ex->op_array->vars[i].name_len == name_len && 1711 !memcmp(ex->op_array->vars[i].name, name, name_len) 1712 ) { 1713 *EX_CV_NUM(ex, i) = NULL; 1714 break; 1715 } 1716 } 1717 } 1718 } 1719 return zend_hash_quick_del(&EG(symbol_table), name, name_len + 1, hash_value); 1720 } 1721 return FAILURE; 1722} 1723/* }}} */ 1724 1725ZEND_API int zend_delete_global_variable(const char *name, int name_len TSRMLS_DC) /* {{{ */ 1726{ 1727 return zend_delete_global_variable_ex(name, name_len, zend_inline_hash_func(name, name_len + 1) TSRMLS_CC); 1728} 1729/* }}} */ 1730 1731ZEND_API void zend_rebuild_symbol_table(TSRMLS_D) /* {{{ */ 1732{ 1733 zend_uint i; 1734 zend_execute_data *ex; 1735 1736 if (!EG(active_symbol_table)) { 1737 1738 /* Search for last called user function */ 1739 ex = EG(current_execute_data); 1740 while (ex && !ex->op_array) { 1741 ex = ex->prev_execute_data; 1742 } 1743 if (ex && ex->symbol_table) { 1744 EG(active_symbol_table) = ex->symbol_table; 1745 return; 1746 } 1747 1748 if (ex && ex->op_array) { 1749 if (EG(symtable_cache_ptr)>=EG(symtable_cache)) { 1750 /*printf("Cache hit! Reusing %x\n", symtable_cache[symtable_cache_ptr]);*/ 1751 EG(active_symbol_table) = *(EG(symtable_cache_ptr)--); 1752 } else { 1753 ALLOC_HASHTABLE(EG(active_symbol_table)); 1754 zend_hash_init(EG(active_symbol_table), ex->op_array->last_var, NULL, ZVAL_PTR_DTOR, 0); 1755 /*printf("Cache miss! Initialized %x\n", EG(active_symbol_table));*/ 1756 } 1757 ex->symbol_table = EG(active_symbol_table); 1758 1759 if (ex->op_array->this_var != -1 && 1760 !*EX_CV_NUM(ex, ex->op_array->this_var) && 1761 EG(This)) { 1762 *EX_CV_NUM(ex, ex->op_array->this_var) = (zval**)EX_CV_NUM(ex, ex->op_array->last_var + ex->op_array->this_var); 1763 **EX_CV_NUM(ex, ex->op_array->this_var) = EG(This); 1764 } 1765 for (i = 0; i < ex->op_array->last_var; i++) { 1766 if (*EX_CV_NUM(ex, i)) { 1767 zend_hash_quick_update(EG(active_symbol_table), 1768 ex->op_array->vars[i].name, 1769 ex->op_array->vars[i].name_len + 1, 1770 ex->op_array->vars[i].hash_value, 1771 (void**)*EX_CV_NUM(ex, i), 1772 sizeof(zval*), 1773 (void**)EX_CV_NUM(ex, i)); 1774 } 1775 } 1776 } 1777 } 1778} 1779/* }}} */ 1780 1781/* 1782 * Local variables: 1783 * tab-width: 4 1784 * c-basic-offset: 4 1785 * indent-tabs-mode: t 1786 * End: 1787 */ 1788