root/Zend/zend_execute_API.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. zend_handle_sigsegv
  2. zend_extension_activator
  3. zend_extension_deactivator
  4. clean_non_persistent_function
  5. clean_non_persistent_function_full
  6. clean_non_persistent_class
  7. clean_non_persistent_class_full
  8. init_executor
  9. zval_call_destructor
  10. zend_unclean_zval_ptr_dtor
  11. zend_throw_or_error
  12. shutdown_destructors
  13. shutdown_executor
  14. get_active_class_name
  15. get_active_function_name
  16. zend_get_executed_filename
  17. zend_get_executed_filename_ex
  18. zend_get_executed_lineno
  19. zend_is_executing
  20. _zval_ptr_dtor
  21. _zval_internal_ptr_dtor
  22. zval_update_constant_ex
  23. zval_update_constant
  24. call_user_function
  25. call_user_function_ex
  26. zend_call_function
  27. zend_lookup_class_ex
  28. zend_lookup_class
  29. zend_get_called_scope
  30. zend_get_this_object
  31. zend_eval_stringl
  32. zend_eval_string
  33. zend_eval_stringl_ex
  34. zend_eval_string_ex
  35. zend_timeout
  36. tq_timer_cb
  37. zend_set_timeout
  38. zend_unset_timeout
  39. zend_fetch_class
  40. zend_fetch_class_by_name
  41. zend_verify_abstract_class_function
  42. zend_verify_abstract_class
  43. zend_delete_global_variable
  44. zend_rebuild_symbol_table
  45. zend_attach_symbol_table
  46. zend_detach_symbol_table
  47. zend_set_local_var
  48. zend_set_local_var_str

   1 /*
   2    +----------------------------------------------------------------------+
   3    | Zend Engine                                                          |
   4    +----------------------------------------------------------------------+
   5    | Copyright (c) 1998-2016 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    |          Dmitry Stogov <dmitry@zend.com>                             |
  18    +----------------------------------------------------------------------+
  19 */
  20 
  21 /* $Id$ */
  22 
  23 #include <stdio.h>
  24 #include <signal.h>
  25 
  26 #include "zend.h"
  27 #include "zend_compile.h"
  28 #include "zend_execute.h"
  29 #include "zend_API.h"
  30 #include "zend_stack.h"
  31 #include "zend_constants.h"
  32 #include "zend_extensions.h"
  33 #include "zend_exceptions.h"
  34 #include "zend_closures.h"
  35 #include "zend_generators.h"
  36 #include "zend_vm.h"
  37 #include "zend_float.h"
  38 #ifdef HAVE_SYS_TIME_H
  39 #include <sys/time.h>
  40 #endif
  41 
  42 ZEND_API void (*zend_execute_ex)(zend_execute_data *execute_data);
  43 ZEND_API void (*zend_execute_internal)(zend_execute_data *execute_data, zval *return_value);
  44 
  45 /* true globals */
  46 ZEND_API const zend_fcall_info empty_fcall_info = { 0, NULL, {{0}, {{0}}, {0}}, NULL, NULL, NULL, NULL, 0, 0 };
  47 ZEND_API const zend_fcall_info_cache empty_fcall_info_cache = { 0, NULL, NULL, NULL, NULL };
  48 
  49 #ifdef ZEND_WIN32
  50 ZEND_TLS HANDLE tq_timer = NULL;
  51 #endif
  52 
  53 #if 0&&ZEND_DEBUG
  54 static void (*original_sigsegv_handler)(int);
  55 static void zend_handle_sigsegv(int dummy) /* {{{ */
  56 {
  57         fflush(stdout);
  58         fflush(stderr);
  59         if (original_sigsegv_handler == zend_handle_sigsegv) {
  60                 signal(SIGSEGV, original_sigsegv_handler);
  61         } else {
  62                 signal(SIGSEGV, SIG_DFL);
  63         }
  64         {
  65 
  66                 fprintf(stderr, "SIGSEGV caught on opcode %d on opline %d of %s() at %s:%d\n\n",
  67                                 active_opline->opcode,
  68                                 active_opline-EG(active_op_array)->opcodes,
  69                                 get_active_function_name(),
  70                                 zend_get_executed_filename(),
  71                                 zend_get_executed_lineno());
  72 /* See http://support.microsoft.com/kb/190351 */
  73 #ifdef ZEND_WIN32
  74                 fflush(stderr);
  75 #endif
  76         }
  77         if (original_sigsegv_handler!=zend_handle_sigsegv) {
  78                 original_sigsegv_handler(dummy);
  79         }
  80 }
  81 /* }}} */
  82 #endif
  83 
  84 static void zend_extension_activator(zend_extension *extension) /* {{{ */
  85 {
  86         if (extension->activate) {
  87                 extension->activate();
  88         }
  89 }
  90 /* }}} */
  91 
  92 static void zend_extension_deactivator(zend_extension *extension) /* {{{ */
  93 {
  94         if (extension->deactivate) {
  95                 extension->deactivate();
  96         }
  97 }
  98 /* }}} */
  99 
 100 static int clean_non_persistent_function(zval *zv) /* {{{ */
 101 {
 102         zend_function *function = Z_PTR_P(zv);
 103         return (function->type == ZEND_INTERNAL_FUNCTION) ? ZEND_HASH_APPLY_STOP : ZEND_HASH_APPLY_REMOVE;
 104 }
 105 /* }}} */
 106 
 107 ZEND_API int clean_non_persistent_function_full(zval *zv) /* {{{ */
 108 {
 109         zend_function *function = Z_PTR_P(zv);
 110         return (function->type == ZEND_INTERNAL_FUNCTION) ? ZEND_HASH_APPLY_KEEP : ZEND_HASH_APPLY_REMOVE;
 111 }
 112 /* }}} */
 113 
 114 static int clean_non_persistent_class(zval *zv) /* {{{ */
 115 {
 116         zend_class_entry *ce = Z_PTR_P(zv);
 117         return (ce->type == ZEND_INTERNAL_CLASS) ? ZEND_HASH_APPLY_STOP : ZEND_HASH_APPLY_REMOVE;
 118 }
 119 /* }}} */
 120 
 121 ZEND_API int clean_non_persistent_class_full(zval *zv) /* {{{ */
 122 {
 123         zend_class_entry *ce = Z_PTR_P(zv);
 124         return (ce->type == ZEND_INTERNAL_CLASS) ? ZEND_HASH_APPLY_KEEP : ZEND_HASH_APPLY_REMOVE;
 125 }
 126 /* }}} */
 127 
 128 void init_executor(void) /* {{{ */
 129 {
 130         zend_init_fpu();
 131 
 132         ZVAL_NULL(&EG(uninitialized_zval));
 133         ZVAL_NULL(&EG(error_zval));
 134 /* destroys stack frame, therefore makes core dumps worthless */
 135 #if 0&&ZEND_DEBUG
 136         original_sigsegv_handler = signal(SIGSEGV, zend_handle_sigsegv);
 137 #endif
 138 
 139         EG(symtable_cache_ptr) = EG(symtable_cache) - 1;
 140         EG(symtable_cache_limit) = EG(symtable_cache) + SYMTABLE_CACHE_SIZE - 1;
 141         EG(no_extensions) = 0;
 142 
 143         EG(function_table) = CG(function_table);
 144         EG(class_table) = CG(class_table);
 145 
 146         EG(in_autoload) = NULL;
 147         EG(autoload_func) = NULL;
 148         EG(error_handling) = EH_NORMAL;
 149 
 150         zend_vm_stack_init();
 151 
 152         zend_hash_init(&EG(symbol_table), 64, NULL, ZVAL_PTR_DTOR, 0);
 153         EG(valid_symbol_table) = 1;
 154 
 155         zend_llist_apply(&zend_extensions, (llist_apply_func_t) zend_extension_activator);
 156 
 157         zend_hash_init(&EG(included_files), 8, NULL, NULL, 0);
 158 
 159         EG(ticks_count) = 0;
 160 
 161         ZVAL_UNDEF(&EG(user_error_handler));
 162 
 163         EG(current_execute_data) = NULL;
 164 
 165         zend_stack_init(&EG(user_error_handlers_error_reporting), sizeof(int));
 166         zend_stack_init(&EG(user_error_handlers), sizeof(zval));
 167         zend_stack_init(&EG(user_exception_handlers), sizeof(zval));
 168 
 169         zend_objects_store_init(&EG(objects_store), 1024);
 170 
 171         EG(full_tables_cleanup) = 0;
 172 #ifdef ZEND_WIN32
 173         EG(timed_out) = 0;
 174 #endif
 175 
 176         EG(exception) = NULL;
 177         EG(prev_exception) = NULL;
 178 
 179         EG(scope) = NULL;
 180 
 181         EG(ht_iterators_count) = sizeof(EG(ht_iterators_slots)) / sizeof(HashTableIterator);
 182         EG(ht_iterators_used) = 0;
 183         EG(ht_iterators) = EG(ht_iterators_slots);
 184         memset(EG(ht_iterators), 0, sizeof(EG(ht_iterators_slots)));
 185 
 186         EG(active) = 1;
 187 }
 188 /* }}} */
 189 
 190 static int zval_call_destructor(zval *zv) /* {{{ */
 191 {
 192         if (Z_TYPE_P(zv) == IS_INDIRECT) {
 193                 zv = Z_INDIRECT_P(zv);
 194         }
 195         if (Z_TYPE_P(zv) == IS_OBJECT && Z_REFCOUNT_P(zv) == 1) {
 196                 return ZEND_HASH_APPLY_REMOVE;
 197         } else {
 198                 return ZEND_HASH_APPLY_KEEP;
 199         }
 200 }
 201 /* }}} */
 202 
 203 static void zend_unclean_zval_ptr_dtor(zval *zv) /* {{{ */
 204 {
 205         if (Z_TYPE_P(zv) == IS_INDIRECT) {
 206                 zv = Z_INDIRECT_P(zv);
 207         }
 208         i_zval_ptr_dtor(zv ZEND_FILE_LINE_CC);
 209 }
 210 /* }}} */
 211 
 212 static void zend_throw_or_error(int fetch_type, zend_class_entry *exception_ce, const char *format, ...) /* {{{ */
 213 {
 214         va_list va;
 215         char *message = NULL;
 216 
 217         va_start(va, format);
 218         zend_vspprintf(&message, 0, format, va);
 219 
 220         if (fetch_type & ZEND_FETCH_CLASS_EXCEPTION) {
 221                 zend_throw_error(exception_ce, "%s", message);
 222         } else {
 223                 zend_error(E_ERROR, "%s", message);
 224         }
 225 
 226         efree(message);
 227         va_end(va);
 228 }
 229 /* }}} */
 230 
 231 void shutdown_destructors(void) /* {{{ */
 232 {
 233         if (CG(unclean_shutdown)) {
 234                 EG(symbol_table).pDestructor = zend_unclean_zval_ptr_dtor;
 235         }
 236         zend_try {
 237                 uint32_t symbols;
 238                 do {
 239                         symbols = zend_hash_num_elements(&EG(symbol_table));
 240                         zend_hash_reverse_apply(&EG(symbol_table), (apply_func_t) zval_call_destructor);
 241                 } while (symbols != zend_hash_num_elements(&EG(symbol_table)));
 242                 zend_objects_store_call_destructors(&EG(objects_store));
 243         } zend_catch {
 244                 /* if we couldn't destruct cleanly, mark all objects as destructed anyway */
 245                 zend_objects_store_mark_destructed(&EG(objects_store));
 246         } zend_end_try();
 247 }
 248 /* }}} */
 249 
 250 void shutdown_executor(void) /* {{{ */
 251 {
 252         zend_function *func;
 253         zend_class_entry *ce;
 254 
 255         zend_try {
 256 
 257 /* Removed because this can not be safely done, e.g. in this situation:
 258    Object 1 creates object 2
 259    Object 3 holds reference to object 2.
 260    Now when 1 and 2 are destroyed, 3 can still access 2 in its destructor, with
 261    very problematic results */
 262 /*              zend_objects_store_call_destructors(&EG(objects_store)); */
 263 
 264 /* Moved after symbol table cleaners, because  some of the cleaners can call
 265    destructors, which would use EG(symtable_cache_ptr) and thus leave leaks */
 266 /*              while (EG(symtable_cache_ptr)>=EG(symtable_cache)) {
 267                         zend_hash_destroy(*EG(symtable_cache_ptr));
 268                         efree(*EG(symtable_cache_ptr));
 269                         EG(symtable_cache_ptr)--;
 270                 }
 271 */
 272                 zend_llist_apply(&zend_extensions, (llist_apply_func_t) zend_extension_deactivator);
 273 
 274                 if (CG(unclean_shutdown)) {
 275                         EG(symbol_table).pDestructor = zend_unclean_zval_ptr_dtor;
 276                 }
 277                 zend_hash_graceful_reverse_destroy(&EG(symbol_table));
 278         } zend_end_try();
 279         EG(valid_symbol_table) = 0;
 280 
 281         zend_try {
 282                 zval *zeh;
 283                 /* remove error handlers before destroying classes and functions,
 284                  * so that if handler used some class, crash would not happen */
 285                 if (Z_TYPE(EG(user_error_handler)) != IS_UNDEF) {
 286                         zeh = &EG(user_error_handler);
 287                         zval_ptr_dtor(zeh);
 288                         ZVAL_UNDEF(&EG(user_error_handler));
 289                 }
 290 
 291                 if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) {
 292                         zeh = &EG(user_exception_handler);
 293                         zval_ptr_dtor(zeh);
 294                         ZVAL_UNDEF(&EG(user_exception_handler));
 295                 }
 296 
 297                 zend_stack_clean(&EG(user_error_handlers_error_reporting), NULL, 1);
 298                 zend_stack_clean(&EG(user_error_handlers), (void (*)(void *))ZVAL_DESTRUCTOR, 1);
 299                 zend_stack_clean(&EG(user_exception_handlers), (void (*)(void *))ZVAL_DESTRUCTOR, 1);
 300         } zend_end_try();
 301 
 302         zend_try {
 303                 /* Cleanup static data for functions and arrays.
 304                  * We need a separate cleanup stage because of the following problem:
 305                  * Suppose we destroy class X, which destroys the class's function table,
 306                  * and in the function table we have function foo() that has static $bar.
 307                  * Now if an object of class X is assigned to $bar, its destructor will be
 308                  * called and will fail since X's function table is in mid-destruction.
 309                  * So we want first of all to clean up all data and then move to tables destruction.
 310                  * Note that only run-time accessed data need to be cleaned up, pre-defined data can
 311                  * not contain objects and thus are not probelmatic */
 312                 if (EG(full_tables_cleanup)) {
 313                         ZEND_HASH_FOREACH_PTR(EG(function_table), func) {
 314                                 if (func->type == ZEND_USER_FUNCTION) {
 315                                         zend_cleanup_op_array_data((zend_op_array *) func);
 316                                 }
 317                         } ZEND_HASH_FOREACH_END();
 318                         ZEND_HASH_REVERSE_FOREACH_PTR(EG(class_table), ce) {
 319                                 if (ce->type == ZEND_USER_CLASS) {
 320                                         zend_cleanup_user_class_data(ce);
 321                                 } else {
 322                                         zend_cleanup_internal_class_data(ce);
 323                                 }
 324                         } ZEND_HASH_FOREACH_END();
 325                 } else {
 326                         ZEND_HASH_REVERSE_FOREACH_PTR(EG(function_table), func) {
 327                                 if (func->type != ZEND_USER_FUNCTION) {
 328                                         break;
 329                                 }
 330                                 zend_cleanup_op_array_data((zend_op_array *) func);
 331                         } ZEND_HASH_FOREACH_END();
 332                         ZEND_HASH_REVERSE_FOREACH_PTR(EG(class_table), ce) {
 333                                 if (ce->type != ZEND_USER_CLASS) {
 334                                         break;
 335                                 }
 336                                 zend_cleanup_user_class_data(ce);
 337                         } ZEND_HASH_FOREACH_END();
 338                         zend_cleanup_internal_classes();
 339                 }
 340         } zend_end_try();
 341 
 342         zend_try {
 343                 zend_llist_destroy(&CG(open_files));
 344         } zend_end_try();
 345 
 346         zend_try {
 347                 zend_close_rsrc_list(&EG(regular_list));
 348         } zend_end_try();
 349 
 350 #if ZEND_DEBUG
 351         if (GC_G(gc_enabled) && !CG(unclean_shutdown)) {
 352                 gc_collect_cycles();
 353         }
 354 #endif
 355 
 356         zend_try {
 357                 zend_objects_store_free_object_storage(&EG(objects_store));
 358 
 359                 zend_vm_stack_destroy();
 360 
 361                 /* Destroy all op arrays */
 362                 if (EG(full_tables_cleanup)) {
 363                         zend_hash_reverse_apply(EG(function_table), clean_non_persistent_function_full);
 364                         zend_hash_reverse_apply(EG(class_table), clean_non_persistent_class_full);
 365                 } else {
 366                         zend_hash_reverse_apply(EG(function_table), clean_non_persistent_function);
 367                         zend_hash_reverse_apply(EG(class_table), clean_non_persistent_class);
 368                 }
 369 
 370                 while (EG(symtable_cache_ptr)>=EG(symtable_cache)) {
 371                         zend_hash_destroy(*EG(symtable_cache_ptr));
 372                         FREE_HASHTABLE(*EG(symtable_cache_ptr));
 373                         EG(symtable_cache_ptr)--;
 374                 }
 375         } zend_end_try();
 376 
 377         zend_try {
 378                 clean_non_persistent_constants();
 379         } zend_end_try();
 380 
 381         zend_try {
 382 #if 0&&ZEND_DEBUG
 383         signal(SIGSEGV, original_sigsegv_handler);
 384 #endif
 385 
 386                 zend_hash_destroy(&EG(included_files));
 387 
 388                 zend_stack_destroy(&EG(user_error_handlers_error_reporting));
 389                 zend_stack_destroy(&EG(user_error_handlers));
 390                 zend_stack_destroy(&EG(user_exception_handlers));
 391                 zend_objects_store_destroy(&EG(objects_store));
 392                 if (EG(in_autoload)) {
 393                         zend_hash_destroy(EG(in_autoload));
 394                         FREE_HASHTABLE(EG(in_autoload));
 395                 }
 396         } zend_end_try();
 397 
 398         zend_shutdown_fpu();
 399 
 400 #ifdef ZEND_DEBUG
 401         if (EG(ht_iterators_used) && !CG(unclean_shutdown)) {
 402                 zend_error(E_WARNING, "Leaked %" PRIu32 " hashtable iterators", EG(ht_iterators_used));
 403         }
 404 #endif
 405 
 406         EG(ht_iterators_used) = 0;
 407         if (EG(ht_iterators) != EG(ht_iterators_slots)) {
 408                 efree(EG(ht_iterators));
 409         }
 410 
 411         EG(active) = 0;
 412 }
 413 /* }}} */
 414 
 415 /* return class name and "::" or "". */
 416 ZEND_API const char *get_active_class_name(const char **space) /* {{{ */
 417 {
 418         zend_function *func;
 419 
 420         if (!zend_is_executing()) {
 421                 if (space) {
 422                         *space = "";
 423                 }
 424                 return "";
 425         }
 426 
 427         func = EG(current_execute_data)->func;
 428         switch (func->type) {
 429                 case ZEND_USER_FUNCTION:
 430                 case ZEND_INTERNAL_FUNCTION:
 431                 {
 432                         zend_class_entry *ce = func->common.scope;
 433 
 434                         if (space) {
 435                                 *space = ce ? "::" : "";
 436                         }
 437                         return ce ? ZSTR_VAL(ce->name) : "";
 438                 }
 439                 default:
 440                         if (space) {
 441                                 *space = "";
 442                         }
 443                         return "";
 444         }
 445 }
 446 /* }}} */
 447 
 448 ZEND_API const char *get_active_function_name(void) /* {{{ */
 449 {
 450         zend_function *func;
 451 
 452         if (!zend_is_executing()) {
 453                 return NULL;
 454         }
 455         func = EG(current_execute_data)->func;
 456         switch (func->type) {
 457                 case ZEND_USER_FUNCTION: {
 458                                 zend_string *function_name = func->common.function_name;
 459 
 460                                 if (function_name) {
 461                                         return ZSTR_VAL(function_name);
 462                                 } else {
 463                                         return "main";
 464                                 }
 465                         }
 466                         break;
 467                 case ZEND_INTERNAL_FUNCTION:
 468                         return ZSTR_VAL(func->common.function_name);
 469                         break;
 470                 default:
 471                         return NULL;
 472         }
 473 }
 474 /* }}} */
 475 
 476 ZEND_API const char *zend_get_executed_filename(void) /* {{{ */
 477 {
 478         zend_execute_data *ex = EG(current_execute_data);
 479 
 480         while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) {
 481                 ex = ex->prev_execute_data;
 482         }
 483         if (ex) {
 484                 return ZSTR_VAL(ex->func->op_array.filename);
 485         } else {
 486                 return "[no active file]";
 487         }
 488 }
 489 /* }}} */
 490 
 491 ZEND_API zend_string *zend_get_executed_filename_ex(void) /* {{{ */
 492 {
 493         zend_execute_data *ex = EG(current_execute_data);
 494 
 495         while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) {
 496                 ex = ex->prev_execute_data;
 497         }
 498         if (ex) {
 499                 return ex->func->op_array.filename;
 500         } else {
 501                 return NULL;
 502         }
 503 }
 504 /* }}} */
 505 
 506 ZEND_API uint zend_get_executed_lineno(void) /* {{{ */
 507 {
 508         zend_execute_data *ex = EG(current_execute_data);
 509 
 510         while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) {
 511                 ex = ex->prev_execute_data;
 512         }
 513         if (ex) {
 514                 if (EG(exception) && ex->opline->opcode == ZEND_HANDLE_EXCEPTION &&
 515                     ex->opline->lineno == 0 && EG(opline_before_exception)) {
 516                         return EG(opline_before_exception)->lineno;
 517                 }
 518                 return ex->opline->lineno;
 519         } else {
 520                 return 0;
 521         }
 522 }
 523 /* }}} */
 524 
 525 ZEND_API zend_bool zend_is_executing(void) /* {{{ */
 526 {
 527         return EG(current_execute_data) != 0;
 528 }
 529 /* }}} */
 530 
 531 ZEND_API void _zval_ptr_dtor(zval *zval_ptr ZEND_FILE_LINE_DC) /* {{{ */
 532 {
 533         i_zval_ptr_dtor(zval_ptr ZEND_FILE_LINE_RELAY_CC);
 534 }
 535 /* }}} */
 536 
 537 ZEND_API void _zval_internal_ptr_dtor(zval *zval_ptr ZEND_FILE_LINE_DC) /* {{{ */
 538 {
 539         if (Z_REFCOUNTED_P(zval_ptr)) {
 540                 Z_DELREF_P(zval_ptr);
 541                 if (Z_REFCOUNT_P(zval_ptr) == 0) {
 542                         _zval_internal_dtor_for_ptr(zval_ptr ZEND_FILE_LINE_CC);
 543                 }
 544         }
 545 }
 546 /* }}} */
 547 
 548 #define IS_VISITED_CONSTANT                     0x80
 549 #define IS_CONSTANT_VISITED(p)          (Z_TYPE_P(p) & IS_VISITED_CONSTANT)
 550 #define MARK_CONSTANT_VISITED(p)        Z_TYPE_INFO_P(p) |= IS_VISITED_CONSTANT
 551 #define RESET_CONSTANT_VISITED(p)       Z_TYPE_INFO_P(p) &= ~IS_VISITED_CONSTANT
 552 
 553 ZEND_API int zval_update_constant_ex(zval *p, zend_bool inline_change, zend_class_entry *scope) /* {{{ */
 554 {
 555         zval *const_value;
 556         char *colon;
 557 
 558         if (IS_CONSTANT_VISITED(p)) {
 559                 zend_throw_error(NULL, "Cannot declare self-referencing constant '%s'", Z_STRVAL_P(p));
 560                 return FAILURE;
 561         } else if (Z_TYPE_P(p) == IS_CONSTANT) {
 562 
 563                 SEPARATE_ZVAL_NOREF(p);
 564                 MARK_CONSTANT_VISITED(p);
 565                 if (Z_CONST_FLAGS_P(p) & IS_CONSTANT_CLASS) {
 566                         ZEND_ASSERT(EG(current_execute_data));
 567                         if (inline_change) {
 568                                 zend_string_release(Z_STR_P(p));
 569                         }
 570                         if (EG(scope) && EG(scope)->name) {
 571                                 ZVAL_STR_COPY(p, EG(scope)->name);
 572                         } else {
 573                                 ZVAL_EMPTY_STRING(p);
 574                         }
 575                 } else if (UNEXPECTED((const_value = zend_get_constant_ex(Z_STR_P(p), scope, Z_CONST_FLAGS_P(p))) == NULL)) {
 576                         char *actual = Z_STRVAL_P(p);
 577 
 578                         if (UNEXPECTED(EG(exception))) {
 579                                 RESET_CONSTANT_VISITED(p);
 580                                 return FAILURE;
 581                         } else if ((colon = (char*)zend_memrchr(Z_STRVAL_P(p), ':', Z_STRLEN_P(p)))) {
 582                                 zend_throw_error(NULL, "Undefined class constant '%s'", Z_STRVAL_P(p));
 583                                 RESET_CONSTANT_VISITED(p);
 584                                 return FAILURE;
 585                         } else {
 586                                 zend_string *save = Z_STR_P(p);
 587                                 char *slash;
 588                                 size_t actual_len = Z_STRLEN_P(p);
 589                                 if ((Z_CONST_FLAGS_P(p) & IS_CONSTANT_UNQUALIFIED) && (slash = (char *)zend_memrchr(actual, '\\', actual_len))) {
 590                                         actual = slash + 1;
 591                                         actual_len -= (actual - Z_STRVAL_P(p));
 592                                         if (inline_change) {
 593                                                 zend_string *s = zend_string_init(actual, actual_len, 0);
 594                                                 Z_STR_P(p) = s;
 595                                                 Z_TYPE_FLAGS_P(p) = IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE;
 596                                         }
 597                                 }
 598                                 if (actual[0] == '\\') {
 599                                         if (inline_change) {
 600                                                 memmove(Z_STRVAL_P(p), Z_STRVAL_P(p)+1, Z_STRLEN_P(p));
 601                                                 --Z_STRLEN_P(p);
 602                                         } else {
 603                                                 ++actual;
 604                                         }
 605                                         --actual_len;
 606                                 }
 607                                 if ((Z_CONST_FLAGS_P(p) & IS_CONSTANT_UNQUALIFIED) == 0) {
 608                                         if (ZSTR_VAL(save)[0] == '\\') {
 609                                                 zend_throw_error(NULL, "Undefined constant '%s'", ZSTR_VAL(save) + 1);
 610                                         } else {
 611                                                 zend_throw_error(NULL, "Undefined constant '%s'", ZSTR_VAL(save));
 612                                         }
 613                                         if (inline_change) {
 614                                                 zend_string_release(save);
 615                                         }
 616                                         RESET_CONSTANT_VISITED(p);
 617                                         return FAILURE;
 618                                 } else {
 619                                         zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",  actual,  actual);
 620                                         if (!inline_change) {
 621                                                 ZVAL_STRINGL(p, actual, actual_len);
 622                                         } else {
 623                                                 Z_TYPE_INFO_P(p) = Z_REFCOUNTED_P(p) ?
 624                                                         IS_STRING_EX : IS_INTERNED_STRING_EX;
 625                                                 if (save && ZSTR_VAL(save) != actual) {
 626                                                         zend_string_release(save);
 627                                                 }
 628                                         }
 629                                 }
 630                         }
 631                 } else {
 632                         if (inline_change) {
 633                                 zend_string_release(Z_STR_P(p));
 634                         }
 635                         ZVAL_COPY_VALUE(p, const_value);
 636                         if (Z_OPT_CONSTANT_P(p)) {
 637                                 if (UNEXPECTED(zval_update_constant_ex(p, 1, NULL) != SUCCESS)) {
 638                                         RESET_CONSTANT_VISITED(p);
 639                                         return FAILURE;
 640                                 }
 641                         }
 642                         zval_opt_copy_ctor(p);
 643                 }
 644         } else if (Z_TYPE_P(p) == IS_CONSTANT_AST) {
 645                 zval tmp;
 646 
 647                 if (UNEXPECTED(zend_ast_evaluate(&tmp, Z_ASTVAL_P(p), scope) != SUCCESS)) {
 648                         return FAILURE;
 649                 }
 650                 if (inline_change) {
 651                         zval_ptr_dtor(p);
 652                 }
 653                 ZVAL_COPY_VALUE(p, &tmp);
 654         }
 655         return SUCCESS;
 656 }
 657 /* }}} */
 658 
 659 ZEND_API int zval_update_constant(zval *pp, zend_bool inline_change) /* {{{ */
 660 {
 661         return zval_update_constant_ex(pp, inline_change, NULL);
 662 }
 663 /* }}} */
 664 
 665 int call_user_function(HashTable *function_table, zval *object, zval *function_name, zval *retval_ptr, uint32_t param_count, zval params[]) /* {{{ */
 666 {
 667         return call_user_function_ex(function_table, object, function_name, retval_ptr, param_count, params, 1, NULL);
 668 }
 669 /* }}} */
 670 
 671 int call_user_function_ex(HashTable *function_table, zval *object, zval *function_name, zval *retval_ptr, uint32_t param_count, zval params[], int no_separation, zend_array *symbol_table) /* {{{ */
 672 {
 673         zend_fcall_info fci;
 674 
 675         fci.size = sizeof(fci);
 676         fci.function_table = function_table;
 677         fci.object = object ? Z_OBJ_P(object) : NULL;
 678         ZVAL_COPY_VALUE(&fci.function_name, function_name);
 679         fci.retval = retval_ptr;
 680         fci.param_count = param_count;
 681         fci.params = params;
 682         fci.no_separation = (zend_bool) no_separation;
 683         fci.symbol_table = symbol_table;
 684 
 685         return zend_call_function(&fci, NULL);
 686 }
 687 /* }}} */
 688 
 689 int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) /* {{{ */
 690 {
 691         uint32_t i;
 692         zend_class_entry *calling_scope = NULL;
 693         zend_execute_data *call, dummy_execute_data;
 694         zend_fcall_info_cache fci_cache_local;
 695         zend_function *func;
 696         zend_class_entry *orig_scope;
 697 
 698         ZVAL_UNDEF(fci->retval);
 699 
 700         if (!EG(active)) {
 701                 return FAILURE; /* executor is already inactive */
 702         }
 703 
 704         if (EG(exception)) {
 705                 return FAILURE; /* we would result in an instable executor otherwise */
 706         }
 707 
 708         switch (fci->size) {
 709                 case sizeof(zend_fcall_info):
 710                         break; /* nothing to do currently */
 711                 default:
 712                         zend_error_noreturn(E_CORE_ERROR, "Corrupted fcall_info provided to zend_call_function()");
 713                         break;
 714         }
 715 
 716         orig_scope = EG(scope);
 717 
 718         /* Initialize execute_data */
 719         if (!EG(current_execute_data)) {
 720                 /* This only happens when we're called outside any execute()'s
 721                  * It shouldn't be strictly necessary to NULL execute_data out,
 722                  * but it may make bugs easier to spot
 723                  */
 724                 memset(&dummy_execute_data, 0, sizeof(zend_execute_data));
 725                 EG(current_execute_data) = &dummy_execute_data;
 726         } else if (EG(current_execute_data)->func &&
 727                    ZEND_USER_CODE(EG(current_execute_data)->func->common.type) &&
 728                    EG(current_execute_data)->opline->opcode != ZEND_DO_FCALL &&
 729                    EG(current_execute_data)->opline->opcode != ZEND_DO_ICALL &&
 730                    EG(current_execute_data)->opline->opcode != ZEND_DO_UCALL &&
 731                    EG(current_execute_data)->opline->opcode != ZEND_DO_FCALL_BY_NAME) {
 732                 /* Insert fake frame in case of include or magic calls */
 733                 dummy_execute_data = *EG(current_execute_data);
 734                 dummy_execute_data.prev_execute_data = EG(current_execute_data);
 735                 dummy_execute_data.call = NULL;
 736                 dummy_execute_data.opline = NULL;
 737                 dummy_execute_data.func = NULL;
 738                 EG(current_execute_data) = &dummy_execute_data;
 739         }
 740 
 741         if (!fci_cache || !fci_cache->initialized) {
 742                 zend_string *callable_name;
 743                 char *error = NULL;
 744 
 745                 if (!fci_cache) {
 746                         fci_cache = &fci_cache_local;
 747                 }
 748 
 749                 if (!zend_is_callable_ex(&fci->function_name, fci->object, IS_CALLABLE_CHECK_SILENT, &callable_name, fci_cache, &error)) {
 750                         if (error) {
 751                                 zend_error(E_WARNING, "Invalid callback %s, %s", ZSTR_VAL(callable_name), error);
 752                                 efree(error);
 753                         }
 754                         if (callable_name) {
 755                                 zend_string_release(callable_name);
 756                         }
 757                         if (EG(current_execute_data) == &dummy_execute_data) {
 758                                 EG(current_execute_data) = dummy_execute_data.prev_execute_data;
 759                         }
 760                         return FAILURE;
 761                 } else if (error) {
 762                         /* Capitalize the first latter of the error message */
 763                         if (error[0] >= 'a' && error[0] <= 'z') {
 764                                 error[0] += ('A' - 'a');
 765                         }
 766                         zend_error(E_DEPRECATED, "%s", error);
 767                         efree(error);
 768                 }
 769                 zend_string_release(callable_name);
 770         }
 771 
 772         func = fci_cache->function_handler;
 773         call = zend_vm_stack_push_call_frame(ZEND_CALL_TOP_FUNCTION,
 774                 func, fci->param_count, fci_cache->called_scope, fci_cache->object);
 775         calling_scope = fci_cache->calling_scope;
 776         fci->object = fci_cache->object;
 777         if (fci->object &&
 778             (!EG(objects_store).object_buckets ||
 779              !IS_OBJ_VALID(EG(objects_store).object_buckets[fci->object->handle]))) {
 780                 if (EG(current_execute_data) == &dummy_execute_data) {
 781                         EG(current_execute_data) = dummy_execute_data.prev_execute_data;
 782                 }
 783                 return FAILURE;
 784         }
 785 
 786         if (func->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) {
 787                 if (func->common.fn_flags & ZEND_ACC_ABSTRACT) {
 788                         zend_throw_error(NULL, "Cannot call abstract method %s::%s()", ZSTR_VAL(func->common.scope->name), ZSTR_VAL(func->common.function_name));
 789                         return FAILURE;
 790                 }
 791                 if (func->common.fn_flags & ZEND_ACC_DEPRECATED) {
 792                         zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated",
 793                                 func->common.scope ? ZSTR_VAL(func->common.scope->name) : "",
 794                                 func->common.scope ? "::" : "",
 795                                 ZSTR_VAL(func->common.function_name));
 796                 }
 797         }
 798 
 799         for (i=0; i<fci->param_count; i++) {
 800                 zval *param;
 801                 zval *arg = &fci->params[i];
 802 
 803                 if (ARG_SHOULD_BE_SENT_BY_REF(func, i + 1)) {
 804                         if (UNEXPECTED(!Z_ISREF_P(arg))) {
 805                                 if (fci->no_separation &&
 806                                         !ARG_MAY_BE_SENT_BY_REF(func, i + 1)) {
 807                                         if (i) {
 808                                                 /* hack to clean up the stack */
 809                                                 ZEND_CALL_NUM_ARGS(call) = i;
 810                                                 zend_vm_stack_free_args(call);
 811                                         }
 812                                         zend_vm_stack_free_call_frame(call);
 813 
 814                                         zend_error(E_WARNING, "Parameter %d to %s%s%s() expected to be a reference, value given",
 815                                                 i+1,
 816                                                 func->common.scope ? ZSTR_VAL(func->common.scope->name) : "",
 817                                                 func->common.scope ? "::" : "",
 818                                                 ZSTR_VAL(func->common.function_name));
 819                                         if (EG(current_execute_data) == &dummy_execute_data) {
 820                                                 EG(current_execute_data) = dummy_execute_data.prev_execute_data;
 821                                         }
 822                                         return FAILURE;
 823                                 }
 824 
 825                                 ZVAL_NEW_REF(arg, arg);
 826                         }
 827                         Z_ADDREF_P(arg);
 828                 } else {
 829                         if (Z_ISREF_P(arg) &&
 830                             !(func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
 831                                 /* don't separate references for __call */
 832                                 arg = Z_REFVAL_P(arg);
 833                         }
 834                         if (Z_OPT_REFCOUNTED_P(arg)) {
 835                                 Z_ADDREF_P(arg);
 836                         }
 837                 }
 838                 param = ZEND_CALL_ARG(call, i+1);
 839                 ZVAL_COPY_VALUE(param, arg);
 840         }
 841 
 842         EG(scope) = calling_scope;
 843         if (func->common.fn_flags & ZEND_ACC_STATIC) {
 844                 fci->object = NULL;
 845         }
 846         Z_OBJ(call->This) = fci->object;
 847 
 848         if (UNEXPECTED(func->op_array.fn_flags & ZEND_ACC_CLOSURE)) {
 849                 ZEND_ASSERT(GC_TYPE((zend_object*)func->op_array.prototype) == IS_OBJECT);
 850                 GC_REFCOUNT((zend_object*)func->op_array.prototype)++;
 851                 ZEND_ADD_CALL_FLAG(call, ZEND_CALL_CLOSURE);
 852         }
 853 
 854         /* PHP-7 doesn't support symbol_table substitution for functions */
 855         ZEND_ASSERT(fci->symbol_table == NULL);
 856 
 857         if (func->type == ZEND_USER_FUNCTION) {
 858                 int call_via_handler = (func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) != 0;
 859                 EG(scope) = func->common.scope;
 860                 call->symbol_table = fci->symbol_table;
 861                 if (EXPECTED((func->op_array.fn_flags & ZEND_ACC_GENERATOR) == 0)) {
 862                         zend_init_execute_data(call, &func->op_array, fci->retval);
 863                         zend_execute_ex(call);
 864                 } else {
 865                         zend_generator_create_zval(call, &func->op_array, fci->retval);
 866                 }
 867                 if (call_via_handler) {
 868                         /* We must re-initialize function again */
 869                         fci_cache->initialized = 0;
 870                 }
 871         } else if (func->type == ZEND_INTERNAL_FUNCTION) {
 872                 int call_via_handler = (func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) != 0;
 873                 ZVAL_NULL(fci->retval);
 874                 if (func->common.scope) {
 875                         EG(scope) = func->common.scope;
 876                 }
 877                 call->prev_execute_data = EG(current_execute_data);
 878                 call->return_value = NULL; /* this is not a constructor call */
 879                 EG(current_execute_data) = call;
 880                 if (EXPECTED(zend_execute_internal == NULL)) {
 881                         /* saves one function call if zend_execute_internal is not used */
 882                         func->internal_function.handler(call, fci->retval);
 883                 } else {
 884                         zend_execute_internal(call, fci->retval);
 885                 }
 886                 EG(current_execute_data) = call->prev_execute_data;
 887                 zend_vm_stack_free_args(call);
 888 
 889                 /*  We shouldn't fix bad extensions here,
 890                         because it can break proper ones (Bug #34045)
 891                 if (!EX(function_state).function->common.return_reference)
 892                 {
 893                         INIT_PZVAL(f->retval);
 894                 }*/
 895                 if (EG(exception)) {
 896                         zval_ptr_dtor(fci->retval);
 897                         ZVAL_UNDEF(fci->retval);
 898                 }
 899 
 900                 if (call_via_handler) {
 901                         /* We must re-initialize function again */
 902                         fci_cache->initialized = 0;
 903                 }
 904         } else { /* ZEND_OVERLOADED_FUNCTION */
 905                 ZVAL_NULL(fci->retval);
 906 
 907                 /* Not sure what should be done here if it's a static method */
 908                 if (fci->object) {
 909                         call->prev_execute_data = EG(current_execute_data);
 910                         EG(current_execute_data) = call;
 911                         fci->object->handlers->call_method(func->common.function_name, fci->object, call, fci->retval);
 912                         EG(current_execute_data) = call->prev_execute_data;
 913                 } else {
 914                         zend_throw_error(NULL, "Cannot call overloaded function for non-object");
 915                 }
 916 
 917                 zend_vm_stack_free_args(call);
 918 
 919                 if (func->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
 920                         zend_string_release(func->common.function_name);
 921                 }
 922                 efree(func);
 923 
 924                 if (EG(exception)) {
 925                         zval_ptr_dtor(fci->retval);
 926                         ZVAL_UNDEF(fci->retval);
 927                 }
 928         }
 929 
 930         EG(scope) = orig_scope;
 931         zend_vm_stack_free_call_frame(call);
 932 
 933         if (EG(current_execute_data) == &dummy_execute_data) {
 934                 EG(current_execute_data) = dummy_execute_data.prev_execute_data;
 935         }
 936 
 937         if (EG(exception)) {
 938                 zend_throw_exception_internal(NULL);
 939         }
 940         return SUCCESS;
 941 }
 942 /* }}} */
 943 
 944 ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, const zval *key, int use_autoload) /* {{{ */
 945 {
 946         zend_class_entry *ce = NULL;
 947         zval args[1];
 948         zval local_retval;
 949         zend_string *lc_name;
 950         zend_fcall_info fcall_info;
 951         zend_fcall_info_cache fcall_cache;
 952 
 953         if (key) {
 954                 lc_name = Z_STR_P(key);
 955         } else {
 956                 if (name == NULL || !ZSTR_LEN(name)) {
 957                         return NULL;
 958                 }
 959 
 960                 if (ZSTR_VAL(name)[0] == '\\') {
 961                         lc_name = zend_string_alloc(ZSTR_LEN(name) - 1, 0);
 962                         zend_str_tolower_copy(ZSTR_VAL(lc_name), ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1);
 963                 } else {
 964                         lc_name = zend_string_tolower(name);
 965                 }
 966         }
 967 
 968         ce = zend_hash_find_ptr(EG(class_table), lc_name);
 969         if (ce) {
 970                 if (!key) {
 971                         zend_string_release(lc_name);
 972                 }
 973                 return ce;
 974         }
 975 
 976         /* The compiler is not-reentrant. Make sure we __autoload() only during run-time
 977          * (doesn't impact functionality of __autoload()
 978         */
 979         if (!use_autoload || zend_is_compiling()) {
 980                 if (!key) {
 981                         zend_string_release(lc_name);
 982                 }
 983                 return NULL;
 984         }
 985 
 986         if (!EG(autoload_func)) {
 987                 zend_function *func = zend_hash_str_find_ptr(EG(function_table), ZEND_AUTOLOAD_FUNC_NAME, sizeof(ZEND_AUTOLOAD_FUNC_NAME) - 1);
 988                 if (func) {
 989                         EG(autoload_func) = func;
 990                 } else {
 991                         if (!key) {
 992                                 zend_string_release(lc_name);
 993                         }
 994                         return NULL;
 995                 }
 996 
 997         }
 998 
 999         /* Verify class name before passing it to __autoload() */
1000         if (strspn(ZSTR_VAL(name), "0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\177\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377\\") != ZSTR_LEN(name)) {
1001                 if (!key) {
1002                         zend_string_release(lc_name);
1003                 }
1004                 return NULL;
1005         }
1006 
1007         if (EG(in_autoload) == NULL) {
1008                 ALLOC_HASHTABLE(EG(in_autoload));
1009                 zend_hash_init(EG(in_autoload), 8, NULL, NULL, 0);
1010         }
1011 
1012         if (zend_hash_add_empty_element(EG(in_autoload), lc_name) == NULL) {
1013                 if (!key) {
1014                         zend_string_release(lc_name);
1015                 }
1016                 return NULL;
1017         }
1018 
1019         ZVAL_UNDEF(&local_retval);
1020 
1021         if (ZSTR_VAL(name)[0] == '\\') {
1022                 ZVAL_STRINGL(&args[0], ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1);
1023         } else {
1024                 ZVAL_STR_COPY(&args[0], name);
1025         }
1026 
1027         fcall_info.size = sizeof(fcall_info);
1028         fcall_info.function_table = EG(function_table);
1029         ZVAL_STR_COPY(&fcall_info.function_name, EG(autoload_func)->common.function_name);
1030         fcall_info.symbol_table = NULL;
1031         fcall_info.retval = &local_retval;
1032         fcall_info.param_count = 1;
1033         fcall_info.params = args;
1034         fcall_info.object = NULL;
1035         fcall_info.no_separation = 1;
1036 
1037         fcall_cache.initialized = 1;
1038         fcall_cache.function_handler = EG(autoload_func);
1039         fcall_cache.calling_scope = NULL;
1040         fcall_cache.called_scope = NULL;
1041         fcall_cache.object = NULL;
1042 
1043         zend_exception_save();
1044         if ((zend_call_function(&fcall_info, &fcall_cache) == SUCCESS) && !EG(exception)) {
1045                 ce = zend_hash_find_ptr(EG(class_table), lc_name);
1046         }
1047         zend_exception_restore();
1048 
1049         zval_ptr_dtor(&args[0]);
1050         zval_dtor(&fcall_info.function_name);
1051 
1052         zend_hash_del(EG(in_autoload), lc_name);
1053 
1054         zval_ptr_dtor(&local_retval);
1055 
1056         if (!key) {
1057                 zend_string_release(lc_name);
1058         }
1059         return ce;
1060 }
1061 /* }}} */
1062 
1063 ZEND_API zend_class_entry *zend_lookup_class(zend_string *name) /* {{{ */
1064 {
1065         return zend_lookup_class_ex(name, NULL, 1);
1066 }
1067 /* }}} */
1068 
1069 ZEND_API zend_class_entry *zend_get_called_scope(zend_execute_data *ex) /* {{{ */
1070 {
1071         while (ex) {
1072                 if (ex->called_scope) {
1073                         return ex->called_scope;
1074                 } else if (ex->func) {
1075                         if (ex->func->type != ZEND_INTERNAL_FUNCTION || ex->func->common.scope) {
1076                                 return ex->called_scope;
1077                         }
1078                 }
1079                 ex = ex->prev_execute_data;
1080         }
1081         return NULL;
1082 }
1083 /* }}} */
1084 
1085 ZEND_API zend_object *zend_get_this_object(zend_execute_data *ex) /* {{{ */
1086 {
1087         while (ex) {
1088                 if (Z_OBJ(ex->This)) {
1089                         return Z_OBJ(ex->This);
1090                 } else if (ex->func) {
1091                         if (ex->func->type != ZEND_INTERNAL_FUNCTION || ex->func->common.scope) {
1092                                 return Z_OBJ(ex->This);
1093                         }
1094                 }
1095                 ex = ex->prev_execute_data;
1096         }
1097         return NULL;
1098 }
1099 /* }}} */
1100 
1101 ZEND_API int zend_eval_stringl(char *str, size_t str_len, zval *retval_ptr, char *string_name) /* {{{ */
1102 {
1103         zval pv;
1104         zend_op_array *new_op_array;
1105         uint32_t original_compiler_options;
1106         int retval;
1107 
1108         if (retval_ptr) {
1109                 ZVAL_NEW_STR(&pv, zend_string_alloc(str_len + sizeof("return ;")-1, 1));
1110                 memcpy(Z_STRVAL(pv), "return ", sizeof("return ") - 1);
1111                 memcpy(Z_STRVAL(pv) + sizeof("return ") - 1, str, str_len);
1112                 Z_STRVAL(pv)[Z_STRLEN(pv) - 1] = ';';
1113                 Z_STRVAL(pv)[Z_STRLEN(pv)] = '\0';
1114         } else {
1115                 ZVAL_STRINGL(&pv, str, str_len);
1116         }
1117 
1118         /*printf("Evaluating '%s'\n", pv.value.str.val);*/
1119 
1120         original_compiler_options = CG(compiler_options);
1121         CG(compiler_options) = ZEND_COMPILE_DEFAULT_FOR_EVAL;
1122         new_op_array = zend_compile_string(&pv, string_name);
1123         CG(compiler_options) = original_compiler_options;
1124 
1125         if (new_op_array) {
1126                 zval local_retval;
1127 
1128                 EG(no_extensions)=1;
1129 
1130                 zend_try {
1131                         ZVAL_UNDEF(&local_retval);
1132                         zend_execute(new_op_array, &local_retval);
1133                 } zend_catch {
1134                         destroy_op_array(new_op_array);
1135                         efree_size(new_op_array, sizeof(zend_op_array));
1136                         zend_bailout();
1137                 } zend_end_try();
1138 
1139                 if (Z_TYPE(local_retval) != IS_UNDEF) {
1140                         if (retval_ptr) {
1141                                 ZVAL_COPY_VALUE(retval_ptr, &local_retval);
1142                         } else {
1143                                 zval_ptr_dtor(&local_retval);
1144                         }
1145                 } else {
1146                         if (retval_ptr) {
1147                                 ZVAL_NULL(retval_ptr);
1148                         }
1149                 }
1150 
1151                 EG(no_extensions)=0;
1152                 destroy_op_array(new_op_array);
1153                 efree_size(new_op_array, sizeof(zend_op_array));
1154                 retval = SUCCESS;
1155         } else {
1156                 retval = FAILURE;
1157         }
1158         zval_dtor(&pv);
1159         return retval;
1160 }
1161 /* }}} */
1162 
1163 ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name) /* {{{ */
1164 {
1165         return zend_eval_stringl(str, strlen(str), retval_ptr, string_name);
1166 }
1167 /* }}} */
1168 
1169 ZEND_API int zend_eval_stringl_ex(char *str, size_t str_len, zval *retval_ptr, char *string_name, int handle_exceptions) /* {{{ */
1170 {
1171         int result;
1172 
1173         result = zend_eval_stringl(str, str_len, retval_ptr, string_name);
1174         if (handle_exceptions && EG(exception)) {
1175                 zend_exception_error(EG(exception), E_ERROR);
1176                 result = FAILURE;
1177         }
1178         return result;
1179 }
1180 /* }}} */
1181 
1182 ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name, int handle_exceptions) /* {{{ */
1183 {
1184         return zend_eval_stringl_ex(str, strlen(str), retval_ptr, string_name, handle_exceptions);
1185 }
1186 /* }}} */
1187 
1188 ZEND_API void zend_timeout(int dummy) /* {{{ */
1189 {
1190 
1191         if (zend_on_timeout) {
1192 #ifdef ZEND_SIGNALS
1193                 /*
1194                    We got here because we got a timeout signal, so we are in a signal handler
1195                    at this point. However, we want to be able to timeout any user-supplied
1196                    shutdown functions, so pretend we are not in a signal handler while we are
1197                    calling these
1198                 */
1199                 SIGG(running) = 0;
1200 #endif
1201                 zend_on_timeout(EG(timeout_seconds));
1202         }
1203 
1204         zend_error_noreturn(E_ERROR, "Maximum execution time of %pd second%s exceeded", EG(timeout_seconds), EG(timeout_seconds) == 1 ? "" : "s");
1205 }
1206 /* }}} */
1207 
1208 #ifdef ZEND_WIN32
1209 VOID CALLBACK tq_timer_cb(PVOID arg, BOOLEAN timed_out)
1210 {
1211         zend_bool *php_timed_out;
1212 
1213         /* The doc states it'll be always true, however it theoretically
1214                 could be FALSE when the thread was signaled. */
1215         if (!timed_out) {
1216                 return;
1217         }
1218 
1219         php_timed_out = (zend_bool *)arg;
1220         *php_timed_out = 1;
1221 }
1222 #endif
1223 
1224 /* This one doesn't exists on QNX */
1225 #ifndef SIGPROF
1226 #define SIGPROF 27
1227 #endif
1228 
1229 void zend_set_timeout(zend_long seconds, int reset_signals) /* {{{ */
1230 {
1231 
1232         EG(timeout_seconds) = seconds;
1233 
1234 #ifdef ZEND_WIN32
1235         if(!seconds) {
1236                 return;
1237         }
1238 
1239         /* Don't use ChangeTimerQueueTimer() as it will not restart an expired
1240                 timer, so we could end up with just an ignored timeout. Instead
1241                 delete and recreate. */
1242         if (NULL != tq_timer) {
1243                 if (!DeleteTimerQueueTimer(NULL, tq_timer, NULL)) {
1244                         EG(timed_out) = 0;
1245                         tq_timer = NULL;
1246                         zend_error_noreturn(E_ERROR, "Could not delete queued timer");
1247                         return;
1248                 }
1249                 tq_timer = NULL;
1250         }
1251 
1252         /* XXX passing NULL means the default timer queue provided by the system is used */
1253         if (!CreateTimerQueueTimer(&tq_timer, NULL, (WAITORTIMERCALLBACK)tq_timer_cb, (VOID*)&EG(timed_out), seconds*1000, 0, WT_EXECUTEONLYONCE)) {
1254                 EG(timed_out) = 0;
1255                 tq_timer = NULL;
1256                 zend_error_noreturn(E_ERROR, "Could not queue new timer");
1257                 return;
1258         }
1259         EG(timed_out) = 0;
1260 #else
1261 #       ifdef HAVE_SETITIMER
1262         {
1263                 struct itimerval t_r;           /* timeout requested */
1264                 int signo;
1265 
1266                 if(seconds) {
1267                         t_r.it_value.tv_sec = seconds;
1268                         t_r.it_value.tv_usec = t_r.it_interval.tv_sec = t_r.it_interval.tv_usec = 0;
1269 
1270 #       ifdef __CYGWIN__
1271                         setitimer(ITIMER_REAL, &t_r, NULL);
1272                 }
1273                 signo = SIGALRM;
1274 #       else
1275                         setitimer(ITIMER_PROF, &t_r, NULL);
1276                 }
1277                 signo = SIGPROF;
1278 #       endif
1279 
1280                 if (reset_signals) {
1281 #       ifdef ZEND_SIGNALS
1282                         zend_signal(signo, zend_timeout);
1283 #       else
1284                         sigset_t sigset;
1285 
1286                         signal(signo, zend_timeout);
1287                         sigemptyset(&sigset);
1288                         sigaddset(&sigset, signo);
1289                         sigprocmask(SIG_UNBLOCK, &sigset, NULL);
1290 #       endif
1291                 }
1292         }
1293 #       endif /* HAVE_SETITIMER */
1294 #endif
1295 }
1296 /* }}} */
1297 
1298 void zend_unset_timeout(void) /* {{{ */
1299 {
1300 #ifdef ZEND_WIN32
1301         if (NULL != tq_timer) {
1302                 if (!DeleteTimerQueueTimer(NULL, tq_timer, NULL)) {
1303                         EG(timed_out) = 0;
1304                         tq_timer = NULL;
1305                         zend_error_noreturn(E_ERROR, "Could not delete queued timer");
1306                         return;
1307                 }
1308                 tq_timer = NULL;
1309         }
1310         EG(timed_out) = 0;
1311 #else
1312 #       ifdef HAVE_SETITIMER
1313         if (EG(timeout_seconds)) {
1314                 struct itimerval no_timeout;
1315 
1316                 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;
1317 
1318 #ifdef __CYGWIN__
1319                 setitimer(ITIMER_REAL, &no_timeout, NULL);
1320 #else
1321                 setitimer(ITIMER_PROF, &no_timeout, NULL);
1322 #endif
1323         }
1324 #       endif
1325 #endif
1326 }
1327 /* }}} */
1328 
1329 zend_class_entry *zend_fetch_class(zend_string *class_name, int fetch_type) /* {{{ */
1330 {
1331         zend_class_entry *ce;
1332         int fetch_sub_type = fetch_type & ZEND_FETCH_CLASS_MASK;
1333 
1334 check_fetch_type:
1335         switch (fetch_sub_type) {
1336                 case ZEND_FETCH_CLASS_SELF:
1337                         if (UNEXPECTED(!EG(scope))) {
1338                                 zend_throw_or_error(fetch_type, NULL, "Cannot access self:: when no class scope is active");
1339                         }
1340                         return EG(scope);
1341                 case ZEND_FETCH_CLASS_PARENT:
1342                         if (UNEXPECTED(!EG(scope))) {
1343                                 zend_throw_or_error(fetch_type, NULL, "Cannot access parent:: when no class scope is active");
1344                                 return NULL;
1345                         }
1346                         if (UNEXPECTED(!EG(scope)->parent)) {
1347                                 zend_throw_or_error(fetch_type, NULL, "Cannot access parent:: when current class scope has no parent");
1348                         }
1349                         return EG(scope)->parent;
1350                 case ZEND_FETCH_CLASS_STATIC:
1351                         ce = zend_get_called_scope(EG(current_execute_data));
1352                         if (UNEXPECTED(!ce)) {
1353                                 zend_throw_or_error(fetch_type, NULL, "Cannot access static:: when no class scope is active");
1354                                 return NULL;
1355                         }
1356                         return ce;
1357                 case ZEND_FETCH_CLASS_AUTO: {
1358                                 fetch_sub_type = zend_get_class_fetch_type(class_name);
1359                                 if (UNEXPECTED(fetch_sub_type != ZEND_FETCH_CLASS_DEFAULT)) {
1360                                         goto check_fetch_type;
1361                                 }
1362                         }
1363                         break;
1364         }
1365 
1366         if (fetch_type & ZEND_FETCH_CLASS_NO_AUTOLOAD) {
1367                 return zend_lookup_class_ex(class_name, NULL, 0);
1368         } else if ((ce = zend_lookup_class_ex(class_name, NULL, 1)) == NULL) {
1369                 if (!(fetch_type & ZEND_FETCH_CLASS_SILENT) && !EG(exception)) {
1370                         if (fetch_sub_type == ZEND_FETCH_CLASS_INTERFACE) {
1371                                 zend_throw_or_error(fetch_type, NULL, "Interface '%s' not found", ZSTR_VAL(class_name));
1372                         } else if (fetch_sub_type == ZEND_FETCH_CLASS_TRAIT) {
1373                                 zend_throw_or_error(fetch_type, NULL, "Trait '%s' not found", ZSTR_VAL(class_name));
1374                         } else {
1375                                 zend_throw_or_error(fetch_type, NULL, "Class '%s' not found", ZSTR_VAL(class_name));
1376                         }
1377                 }
1378                 return NULL;
1379         }
1380         return ce;
1381 }
1382 /* }}} */
1383 
1384 zend_class_entry *zend_fetch_class_by_name(zend_string *class_name, const zval *key, int fetch_type) /* {{{ */
1385 {
1386         zend_class_entry *ce;
1387 
1388         if (fetch_type & ZEND_FETCH_CLASS_NO_AUTOLOAD) {
1389                 return zend_lookup_class_ex(class_name, key, 0);
1390         } else if ((ce = zend_lookup_class_ex(class_name, key, 1)) == NULL) {
1391                 if ((fetch_type & ZEND_FETCH_CLASS_SILENT) == 0 && !EG(exception)) {
1392                         if ((fetch_type & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_INTERFACE) {
1393                                 zend_throw_or_error(fetch_type, NULL, "Interface '%s' not found", ZSTR_VAL(class_name));
1394                         } else if ((fetch_type & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_TRAIT) {
1395                                 zend_throw_or_error(fetch_type, NULL, "Trait '%s' not found", ZSTR_VAL(class_name));
1396                         } else {
1397                                 zend_throw_or_error(fetch_type, NULL, "Class '%s' not found", ZSTR_VAL(class_name));
1398                         }
1399                 }
1400                 return NULL;
1401         }
1402         return ce;
1403 }
1404 /* }}} */
1405 
1406 #define MAX_ABSTRACT_INFO_CNT 3
1407 #define MAX_ABSTRACT_INFO_FMT "%s%s%s%s"
1408 #define DISPLAY_ABSTRACT_FN(idx) \
1409         ai.afn[idx] ? ZEND_FN_SCOPE_NAME(ai.afn[idx]) : "", \
1410         ai.afn[idx] ? "::" : "", \
1411         ai.afn[idx] ? ZSTR_VAL(ai.afn[idx]->common.function_name) : "", \
1412         ai.afn[idx] && ai.afn[idx + 1] ? ", " : (ai.afn[idx] && ai.cnt > MAX_ABSTRACT_INFO_CNT ? ", ..." : "")
1413 
1414 typedef struct _zend_abstract_info {
1415         zend_function *afn[MAX_ABSTRACT_INFO_CNT + 1];
1416         int cnt;
1417         int ctor;
1418 } zend_abstract_info;
1419 
1420 static void zend_verify_abstract_class_function(zend_function *fn, zend_abstract_info *ai) /* {{{ */
1421 {
1422         if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
1423                 if (ai->cnt < MAX_ABSTRACT_INFO_CNT) {
1424                         ai->afn[ai->cnt] = fn;
1425                 }
1426                 if (fn->common.fn_flags & ZEND_ACC_CTOR) {
1427                         if (!ai->ctor) {
1428                                 ai->cnt++;
1429                                 ai->ctor = 1;
1430                         } else {
1431                                 ai->afn[ai->cnt] = NULL;
1432                         }
1433                 } else {
1434                         ai->cnt++;
1435                 }
1436         }
1437 }
1438 /* }}} */
1439 
1440 void zend_verify_abstract_class(zend_class_entry *ce) /* {{{ */
1441 {
1442         zend_function *func;
1443         zend_abstract_info ai;
1444 
1445         if ((ce->ce_flags & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS) && !(ce->ce_flags & (ZEND_ACC_TRAIT | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS))) {
1446                 memset(&ai, 0, sizeof(ai));
1447 
1448                 ZEND_HASH_FOREACH_PTR(&ce->function_table, func) {
1449                         zend_verify_abstract_class_function(func, &ai);
1450                 } ZEND_HASH_FOREACH_END();
1451 
1452                 if (ai.cnt) {
1453                         zend_error_noreturn(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 ")",
1454                                 ZSTR_VAL(ce->name), ai.cnt,
1455                                 ai.cnt > 1 ? "s" : "",
1456                                 DISPLAY_ABSTRACT_FN(0),
1457                                 DISPLAY_ABSTRACT_FN(1),
1458                                 DISPLAY_ABSTRACT_FN(2)
1459                                 );
1460                 }
1461         }
1462 }
1463 /* }}} */
1464 
1465 ZEND_API int zend_delete_global_variable(zend_string *name) /* {{{ */
1466 {
1467     return zend_hash_del_ind(&EG(symbol_table), name);
1468 }
1469 /* }}} */
1470 
1471 ZEND_API zend_array *zend_rebuild_symbol_table(void) /* {{{ */
1472 {
1473         zend_execute_data *ex;
1474         zend_array *symbol_table;
1475 
1476         /* Search for last called user function */
1477         ex = EG(current_execute_data);
1478         while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->common.type))) {
1479                 ex = ex->prev_execute_data;
1480         }
1481         if (!ex) {
1482                 return NULL;
1483         }
1484         if (ex->symbol_table) {
1485                 return ex->symbol_table;
1486         }
1487 
1488         if (EG(symtable_cache_ptr) >= EG(symtable_cache)) {
1489                 /*printf("Cache hit!  Reusing %x\n", symtable_cache[symtable_cache_ptr]);*/
1490                 symbol_table = ex->symbol_table = *(EG(symtable_cache_ptr)--);
1491                 if (!ex->func->op_array.last_var) {
1492                         return symbol_table;
1493                 }
1494                 zend_hash_extend(symbol_table, ex->func->op_array.last_var, 0);
1495         } else {
1496                 symbol_table = ex->symbol_table = emalloc(sizeof(zend_array));
1497                 zend_hash_init(symbol_table, ex->func->op_array.last_var, NULL, ZVAL_PTR_DTOR, 0);
1498                 if (!ex->func->op_array.last_var) {
1499                         return symbol_table;
1500                 }
1501                 zend_hash_real_init(symbol_table, 0);
1502                 /*printf("Cache miss!  Initialized %x\n", EG(active_symbol_table));*/
1503         }
1504         if (EXPECTED(ex->func->op_array.last_var)) {
1505                 zend_string **str = ex->func->op_array.vars;
1506                 zend_string **end = str + ex->func->op_array.last_var;
1507                 zval *var = ZEND_CALL_VAR_NUM(ex, 0);
1508 
1509                 do {
1510                         _zend_hash_append_ind(symbol_table, *str, var);
1511                         str++;
1512                         var++;
1513                 } while (str != end);
1514         }
1515         return symbol_table;
1516 }
1517 /* }}} */
1518 
1519 ZEND_API void zend_attach_symbol_table(zend_execute_data *execute_data) /* {{{ */
1520 {
1521         zend_op_array *op_array = &execute_data->func->op_array;
1522         HashTable *ht = execute_data->symbol_table;
1523 
1524         /* copy real values from symbol table into CV slots and create
1525            INDIRECT references to CV in symbol table  */
1526         if (EXPECTED(op_array->last_var)) {
1527                 zend_string **str = op_array->vars;
1528                 zend_string **end = str + op_array->last_var;
1529                 zval *var = EX_VAR_NUM(0);
1530 
1531                 do {
1532                         zval *zv = zend_hash_find(ht, *str);
1533 
1534                         if (zv) {
1535                                 if (Z_TYPE_P(zv) == IS_INDIRECT) {
1536                                         zval *val = Z_INDIRECT_P(zv);
1537 
1538                                         ZVAL_COPY_VALUE(var, val);
1539                                 } else {
1540                                         ZVAL_COPY_VALUE(var, zv);
1541                                 }
1542                         } else {
1543                                 ZVAL_UNDEF(var);
1544                                 zv = zend_hash_add_new(ht, *str, var);
1545                         }
1546                         ZVAL_INDIRECT(zv, var);
1547                         str++;
1548                         var++;
1549                 } while (str != end);
1550         }
1551 }
1552 /* }}} */
1553 
1554 ZEND_API void zend_detach_symbol_table(zend_execute_data *execute_data) /* {{{ */
1555 {
1556         zend_op_array *op_array = &execute_data->func->op_array;
1557         HashTable *ht = execute_data->symbol_table;
1558 
1559         /* copy real values from CV slots into symbol table */
1560         if (EXPECTED(op_array->last_var)) {
1561                 zend_string **str = op_array->vars;
1562                 zend_string **end = str + op_array->last_var;
1563                 zval *var = EX_VAR_NUM(0);
1564 
1565                 do {
1566                         if (Z_TYPE_P(var) == IS_UNDEF) {
1567                                 zend_hash_del(ht, *str);
1568                         } else {
1569                                 zend_hash_update(ht, *str, var);
1570                                 ZVAL_UNDEF(var);
1571                         }
1572                         str++;
1573                         var++;
1574                 } while (str != end);
1575         }
1576 }
1577 /* }}} */
1578 
1579 ZEND_API int zend_set_local_var(zend_string *name, zval *value, int force) /* {{{ */
1580 {
1581         zend_execute_data *execute_data = EG(current_execute_data);
1582 
1583         while (execute_data && (!execute_data->func || !ZEND_USER_CODE(execute_data->func->common.type))) {
1584                 execute_data = execute_data->prev_execute_data;
1585         }
1586 
1587         if (execute_data) {
1588                 if (!execute_data->symbol_table) {
1589                         zend_ulong h = zend_string_hash_val(name);
1590                         zend_op_array *op_array = &execute_data->func->op_array;
1591 
1592                         if (EXPECTED(op_array->last_var)) {
1593                                 zend_string **str = op_array->vars;
1594                                 zend_string **end = str + op_array->last_var;
1595 
1596                                 do {
1597                                         if (ZSTR_H(*str) == h &&
1598                                             ZSTR_LEN(*str) == ZSTR_LEN(name) &&
1599                                             memcmp(ZSTR_VAL(*str), ZSTR_VAL(name), ZSTR_LEN(name)) == 0) {
1600                                                 zval *var = EX_VAR_NUM(str - op_array->vars);
1601                                                 ZVAL_COPY_VALUE(var, value);
1602                                                 return SUCCESS;
1603                                         }
1604                                         str++;
1605                                 } while (str != end);
1606                         }
1607                         if (force) {
1608                                 zend_array *symbol_table = zend_rebuild_symbol_table();
1609                                 if (symbol_table) {
1610                                         return zend_hash_update(symbol_table, name, value) ? SUCCESS : FAILURE;;
1611                                 }
1612                         }
1613                 } else {
1614                         return (zend_hash_update_ind(execute_data->symbol_table, name, value) != NULL) ? SUCCESS : FAILURE;
1615                 }
1616         }
1617         return FAILURE;
1618 }
1619 /* }}} */
1620 
1621 ZEND_API int zend_set_local_var_str(const char *name, size_t len, zval *value, int force) /* {{{ */
1622 {
1623         zend_execute_data *execute_data = EG(current_execute_data);
1624 
1625         while (execute_data && (!execute_data->func || !ZEND_USER_CODE(execute_data->func->common.type))) {
1626                 execute_data = execute_data->prev_execute_data;
1627         }
1628 
1629         if (execute_data) {
1630                 if (!execute_data->symbol_table) {
1631                         zend_ulong h = zend_hash_func(name, len);
1632                         zend_op_array *op_array = &execute_data->func->op_array;
1633                         if (EXPECTED(op_array->last_var)) {
1634                                 zend_string **str = op_array->vars;
1635                                 zend_string **end = str + op_array->last_var;
1636 
1637                                 do {
1638                                         if (ZSTR_H(*str) == h &&
1639                                             ZSTR_LEN(*str) == len &&
1640                                             memcmp(ZSTR_VAL(*str), name, len) == 0) {
1641                                                 zval *var = EX_VAR_NUM(str - op_array->vars);
1642                                                 zval_ptr_dtor(var);
1643                                                 ZVAL_COPY_VALUE(var, value);
1644                                                 return SUCCESS;
1645                                         }
1646                                         str++;
1647                                 } while (str != end);
1648                         }
1649                         if (force) {
1650                                 zend_array *symbol_table = zend_rebuild_symbol_table();
1651                                 if (symbol_table) {
1652                                         return zend_hash_str_update(symbol_table, name, len, value) ? SUCCESS : FAILURE;;
1653                                 }
1654                         }
1655                 } else {
1656                         return (zend_hash_str_update_ind(execute_data->symbol_table, name, len, value) != NULL) ? SUCCESS : FAILURE;
1657                 }
1658         }
1659         return FAILURE;
1660 }
1661 /* }}} */
1662 
1663 /*
1664  * Local variables:
1665  * tab-width: 4
1666  * c-basic-offset: 4
1667  * indent-tabs-mode: t
1668  * End:
1669  */

/* [<][>][^][v][top][bottom][index][help] */