1 /* 2 +----------------------------------------------------------------------+ 3 | Zend Engine | 4 +----------------------------------------------------------------------+ 5 | Copyright (c) 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@php.net> | 16 | Zeev Suraski <zeev@php.net> | 17 +----------------------------------------------------------------------+ 18 */ 19 20 #include "zend.h" 21 #include "zend_extensions.h" 22 #include "zend_modules.h" 23 #include "zend_constants.h" 24 #include "zend_list.h" 25 #include "zend_API.h" 26 #include "zend_exceptions.h" 27 #include "zend_builtin_functions.h" 28 #include "zend_ini.h" 29 #include "zend_vm.h" 30 #include "zend_dtrace.h" 31 #include "zend_virtual_cwd.h" 32 #include "zend_smart_str.h" 33 #include "zend_smart_string.h" 34 #include "zend_cpuinfo.h" 35 #include "zend_attributes.h" 36 #include "zend_observer.h" 37 38 static size_t global_map_ptr_last = 0; 39 40 #ifdef ZTS 41 ZEND_API int compiler_globals_id; 42 ZEND_API int executor_globals_id; 43 ZEND_API size_t compiler_globals_offset; 44 ZEND_API size_t executor_globals_offset; 45 static HashTable *global_function_table = NULL; 46 static HashTable *global_class_table = NULL; 47 static HashTable *global_constants_table = NULL; 48 static HashTable *global_auto_globals_table = NULL; 49 static HashTable *global_persistent_list = NULL; 50 ZEND_TSRMLS_CACHE_DEFINE() 51 # define GLOBAL_FUNCTION_TABLE global_function_table 52 # define GLOBAL_CLASS_TABLE global_class_table 53 # define GLOBAL_CONSTANTS_TABLE global_constants_table 54 # define GLOBAL_AUTO_GLOBALS_TABLE global_auto_globals_table 55 #else 56 # define GLOBAL_FUNCTION_TABLE CG(function_table) 57 # define GLOBAL_CLASS_TABLE CG(class_table) 58 # define GLOBAL_AUTO_GLOBALS_TABLE CG(auto_globals) 59 # define GLOBAL_CONSTANTS_TABLE EG(zend_constants) 60 #endif 61 62 ZEND_API zend_utility_values zend_uv; 63 ZEND_API zend_bool zend_dtrace_enabled; 64 65 /* version information */ 66 static char *zend_version_info; 67 static uint32_t zend_version_info_length; 68 #define ZEND_CORE_VERSION_INFO "Zend Engine v" ZEND_VERSION ", Copyright (c) Zend Technologies\n" 69 #define PRINT_ZVAL_INDENT 4 70 71 /* true multithread-shared globals */ 72 ZEND_API zend_class_entry *zend_standard_class_def = NULL; 73 ZEND_API size_t (*zend_printf)(const char *format, ...); 74 ZEND_API zend_write_func_t zend_write; 75 ZEND_API FILE *(*zend_fopen)(const char *filename, zend_string **opened_path); 76 ZEND_API zend_result (*zend_stream_open_function)(const char *filename, zend_file_handle *handle); 77 ZEND_API void (*zend_ticks_function)(int ticks); 78 ZEND_API void (*zend_interrupt_function)(zend_execute_data *execute_data); 79 ZEND_API void (*zend_error_cb)(int type, const char *error_filename, const uint32_t error_lineno, zend_string *message); 80 void (*zend_printf_to_smart_string)(smart_string *buf, const char *format, va_list ap); 81 void (*zend_printf_to_smart_str)(smart_str *buf, const char *format, va_list ap); 82 ZEND_API char *(*zend_getenv)(const char *name, size_t name_len); 83 ZEND_API zend_string *(*zend_resolve_path)(const char *filename, size_t filename_len); 84 ZEND_API zend_result (*zend_post_startup_cb)(void) = NULL; 85 ZEND_API void (*zend_post_shutdown_cb)(void) = NULL; 86 ZEND_API zend_result (*zend_preload_autoload)(zend_string *filename) = NULL; 87 88 /* This callback must be signal handler safe! */ 89 void (*zend_on_timeout)(int seconds); 90 91 static void (*zend_message_dispatcher_p)(zend_long message, const void *data); 92 static zval *(*zend_get_configuration_directive_p)(zend_string *name); 93 94 #if ZEND_RC_DEBUG 95 ZEND_API zend_bool zend_rc_debug = 0; 96 #endif 97 98 static ZEND_INI_MH(OnUpdateErrorReporting) /* {{{ */ 99 { 100 if (!new_value) { 101 EG(error_reporting) = E_ALL; 102 } else { 103 EG(error_reporting) = atoi(ZSTR_VAL(new_value)); 104 } 105 return SUCCESS; 106 } 107 /* }}} */ 108 109 static ZEND_INI_MH(OnUpdateGCEnabled) /* {{{ */ 110 { 111 zend_bool val; 112 113 val = zend_ini_parse_bool(new_value); 114 gc_enable(val); 115 116 return SUCCESS; 117 } 118 /* }}} */ 119 120 static ZEND_INI_DISP(zend_gc_enabled_displayer_cb) /* {{{ */ 121 { 122 if (gc_enabled()) { 123 ZEND_PUTS("On"); 124 } else { 125 ZEND_PUTS("Off"); 126 } 127 } 128 /* }}} */ 129 130 131 static ZEND_INI_MH(OnUpdateScriptEncoding) /* {{{ */ 132 { 133 if (!CG(multibyte)) { 134 return FAILURE; 135 } 136 if (!zend_multibyte_get_functions()) { 137 return SUCCESS; 138 } 139 return zend_multibyte_set_script_encoding_by_string(new_value ? ZSTR_VAL(new_value) : NULL, new_value ? ZSTR_LEN(new_value) : 0); 140 } 141 /* }}} */ 142 143 static ZEND_INI_MH(OnUpdateAssertions) /* {{{ */ 144 { 145 zend_long *p = (zend_long *) ZEND_INI_GET_ADDR(); 146 147 zend_long val = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value)); 148 149 if (stage != ZEND_INI_STAGE_STARTUP && 150 stage != ZEND_INI_STAGE_SHUTDOWN && 151 *p != val && 152 (*p < 0 || val < 0)) { 153 zend_error(E_WARNING, "zend.assertions may be completely enabled or disabled only in php.ini"); 154 return FAILURE; 155 } 156 157 *p = val; 158 return SUCCESS; 159 } 160 /* }}} */ 161 162 static ZEND_INI_MH(OnSetExceptionStringParamMaxLen) /* {{{ */ 163 { 164 zend_long i; 165 166 ZEND_ATOL(i, ZSTR_VAL(new_value)); 167 if (i >= 0 && i <= 1000000) { 168 EG(exception_string_param_max_len) = i; 169 return SUCCESS; 170 } else { 171 return FAILURE; 172 } 173 } 174 /* }}} */ 175 176 #if ZEND_DEBUG 177 # define SIGNAL_CHECK_DEFAULT "1" 178 #else 179 # define SIGNAL_CHECK_DEFAULT "0" 180 #endif 181 182 ZEND_INI_BEGIN() 183 ZEND_INI_ENTRY("error_reporting", NULL, ZEND_INI_ALL, OnUpdateErrorReporting) 184 STD_ZEND_INI_ENTRY("zend.assertions", "1", ZEND_INI_ALL, OnUpdateAssertions, assertions, zend_executor_globals, executor_globals) 185 ZEND_INI_ENTRY3_EX("zend.enable_gc", "1", ZEND_INI_ALL, OnUpdateGCEnabled, NULL, NULL, NULL, zend_gc_enabled_displayer_cb) 186 STD_ZEND_INI_BOOLEAN("zend.multibyte", "0", ZEND_INI_PERDIR, OnUpdateBool, multibyte, zend_compiler_globals, compiler_globals) 187 ZEND_INI_ENTRY("zend.script_encoding", NULL, ZEND_INI_ALL, OnUpdateScriptEncoding) 188 STD_ZEND_INI_BOOLEAN("zend.detect_unicode", "1", ZEND_INI_ALL, OnUpdateBool, detect_unicode, zend_compiler_globals, compiler_globals) 189 #ifdef ZEND_SIGNALS 190 STD_ZEND_INI_BOOLEAN("zend.signal_check", SIGNAL_CHECK_DEFAULT, ZEND_INI_SYSTEM, OnUpdateBool, check, zend_signal_globals_t, zend_signal_globals) 191 #endif 192 STD_ZEND_INI_BOOLEAN("zend.exception_ignore_args", "0", ZEND_INI_ALL, OnUpdateBool, exception_ignore_args, zend_executor_globals, executor_globals) 193 STD_ZEND_INI_ENTRY("zend.exception_string_param_max_len", "15", ZEND_INI_ALL, OnSetExceptionStringParamMaxLen, exception_string_param_max_len, zend_executor_globals, executor_globals) 194 ZEND_INI_END() 195 196 ZEND_API size_t zend_vspprintf(char **pbuf, size_t max_len, const char *format, va_list ap) /* {{{ */ 197 { 198 smart_string buf = {0}; 199 200 /* since there are places where (v)spprintf called without checking for null, 201 a bit of defensive coding here */ 202 if (!pbuf) { 203 return 0; 204 } 205 206 zend_printf_to_smart_string(&buf, format, ap); 207 208 if (max_len && buf.len > max_len) { 209 buf.len = max_len; 210 } 211 212 smart_string_0(&buf); 213 214 if (buf.c) { 215 *pbuf = buf.c; 216 return buf.len; 217 } else { 218 *pbuf = estrndup("", 0); 219 return 0; 220 } 221 } 222 /* }}} */ 223 224 ZEND_API size_t zend_spprintf(char **message, size_t max_len, const char *format, ...) /* {{{ */ 225 { 226 va_list arg; 227 size_t len; 228 229 va_start(arg, format); 230 len = zend_vspprintf(message, max_len, format, arg); 231 va_end(arg); 232 return len; 233 } 234 /* }}} */ 235 236 ZEND_API size_t zend_spprintf_unchecked(char **message, size_t max_len, const char *format, ...) /* {{{ */ 237 { 238 va_list arg; 239 size_t len; 240 241 va_start(arg, format); 242 len = zend_vspprintf(message, max_len, format, arg); 243 va_end(arg); 244 return len; 245 } 246 /* }}} */ 247 248 ZEND_API zend_string *zend_vstrpprintf(size_t max_len, const char *format, va_list ap) /* {{{ */ 249 { 250 smart_str buf = {0}; 251 252 zend_printf_to_smart_str(&buf, format, ap); 253 254 if (!buf.s) { 255 return ZSTR_EMPTY_ALLOC(); 256 } 257 258 if (max_len && ZSTR_LEN(buf.s) > max_len) { 259 ZSTR_LEN(buf.s) = max_len; 260 } 261 262 smart_str_0(&buf); 263 return buf.s; 264 } 265 /* }}} */ 266 267 ZEND_API zend_string *zend_strpprintf(size_t max_len, const char *format, ...) /* {{{ */ 268 { 269 va_list arg; 270 zend_string *str; 271 272 va_start(arg, format); 273 str = zend_vstrpprintf(max_len, format, arg); 274 va_end(arg); 275 return str; 276 } 277 /* }}} */ 278 279 ZEND_API zend_string *zend_strpprintf_unchecked(size_t max_len, const char *format, ...) /* {{{ */ 280 { 281 va_list arg; 282 zend_string *str; 283 284 va_start(arg, format); 285 str = zend_vstrpprintf(max_len, format, arg); 286 va_end(arg); 287 return str; 288 } 289 /* }}} */ 290 291 static void zend_print_zval_r_to_buf(smart_str *buf, zval *expr, int indent); 292 293 static void print_hash(smart_str *buf, HashTable *ht, int indent, zend_bool is_object) /* {{{ */ 294 { 295 zval *tmp; 296 zend_string *string_key; 297 zend_ulong num_key; 298 int i; 299 300 for (i = 0; i < indent; i++) { 301 smart_str_appendc(buf, ' '); 302 } 303 smart_str_appends(buf, "(\n"); 304 indent += PRINT_ZVAL_INDENT; 305 ZEND_HASH_FOREACH_KEY_VAL_IND(ht, num_key, string_key, tmp) { 306 for (i = 0; i < indent; i++) { 307 smart_str_appendc(buf, ' '); 308 } 309 smart_str_appendc(buf, '['); 310 if (string_key) { 311 if (is_object) { 312 const char *prop_name, *class_name; 313 size_t prop_len; 314 int mangled = zend_unmangle_property_name_ex(string_key, &class_name, &prop_name, &prop_len); 315 316 smart_str_appendl(buf, prop_name, prop_len); 317 if (class_name && mangled == SUCCESS) { 318 if (class_name[0] == '*') { 319 smart_str_appends(buf, ":protected"); 320 } else { 321 smart_str_appends(buf, ":"); 322 smart_str_appends(buf, class_name); 323 smart_str_appends(buf, ":private"); 324 } 325 } 326 } else { 327 smart_str_append(buf, string_key); 328 } 329 } else { 330 smart_str_append_long(buf, num_key); 331 } 332 smart_str_appends(buf, "] => "); 333 zend_print_zval_r_to_buf(buf, tmp, indent+PRINT_ZVAL_INDENT); 334 smart_str_appends(buf, "\n"); 335 } ZEND_HASH_FOREACH_END(); 336 indent -= PRINT_ZVAL_INDENT; 337 for (i = 0; i < indent; i++) { 338 smart_str_appendc(buf, ' '); 339 } 340 smart_str_appends(buf, ")\n"); 341 } 342 /* }}} */ 343 344 static void print_flat_hash(HashTable *ht) /* {{{ */ 345 { 346 zval *tmp; 347 zend_string *string_key; 348 zend_ulong num_key; 349 int i = 0; 350 351 ZEND_HASH_FOREACH_KEY_VAL_IND(ht, num_key, string_key, tmp) { 352 if (i++ > 0) { 353 ZEND_PUTS(","); 354 } 355 ZEND_PUTS("["); 356 if (string_key) { 357 ZEND_WRITE(ZSTR_VAL(string_key), ZSTR_LEN(string_key)); 358 } else { 359 zend_printf(ZEND_ULONG_FMT, num_key); 360 } 361 ZEND_PUTS("] => "); 362 zend_print_flat_zval_r(tmp); 363 } ZEND_HASH_FOREACH_END(); 364 } 365 /* }}} */ 366 367 ZEND_API bool zend_make_printable_zval(zval *expr, zval *expr_copy) /* {{{ */ 368 { 369 if (Z_TYPE_P(expr) == IS_STRING) { 370 return 0; 371 } else { 372 ZVAL_STR(expr_copy, zval_get_string_func(expr)); 373 return 1; 374 } 375 } 376 /* }}} */ 377 378 ZEND_API size_t zend_print_zval(zval *expr, int indent) /* {{{ */ 379 { 380 zend_string *tmp_str; 381 zend_string *str = zval_get_tmp_string(expr, &tmp_str); 382 size_t len = ZSTR_LEN(str); 383 384 if (len != 0) { 385 zend_write(ZSTR_VAL(str), len); 386 } 387 388 zend_tmp_string_release(tmp_str); 389 return len; 390 } 391 /* }}} */ 392 393 ZEND_API void zend_print_flat_zval_r(zval *expr) /* {{{ */ 394 { 395 switch (Z_TYPE_P(expr)) { 396 case IS_ARRAY: 397 ZEND_PUTS("Array ("); 398 if (!(GC_FLAGS(Z_ARRVAL_P(expr)) & GC_IMMUTABLE)) { 399 if (GC_IS_RECURSIVE(Z_ARRVAL_P(expr))) { 400 ZEND_PUTS(" *RECURSION*"); 401 return; 402 } 403 GC_PROTECT_RECURSION(Z_ARRVAL_P(expr)); 404 } 405 print_flat_hash(Z_ARRVAL_P(expr)); 406 ZEND_PUTS(")"); 407 GC_TRY_UNPROTECT_RECURSION(Z_ARRVAL_P(expr)); 408 break; 409 case IS_OBJECT: 410 { 411 HashTable *properties; 412 zend_string *class_name = Z_OBJ_HANDLER_P(expr, get_class_name)(Z_OBJ_P(expr)); 413 zend_printf("%s Object (", ZSTR_VAL(class_name)); 414 zend_string_release_ex(class_name, 0); 415 416 if (GC_IS_RECURSIVE(Z_COUNTED_P(expr))) { 417 ZEND_PUTS(" *RECURSION*"); 418 return; 419 } 420 421 properties = Z_OBJPROP_P(expr); 422 if (properties) { 423 GC_PROTECT_RECURSION(Z_OBJ_P(expr)); 424 print_flat_hash(properties); 425 GC_UNPROTECT_RECURSION(Z_OBJ_P(expr)); 426 } 427 ZEND_PUTS(")"); 428 break; 429 } 430 case IS_REFERENCE: 431 zend_print_flat_zval_r(Z_REFVAL_P(expr)); 432 break; 433 default: 434 zend_print_zval(expr, 0); 435 break; 436 } 437 } 438 /* }}} */ 439 440 static void zend_print_zval_r_to_buf(smart_str *buf, zval *expr, int indent) /* {{{ */ 441 { 442 switch (Z_TYPE_P(expr)) { 443 case IS_ARRAY: 444 smart_str_appends(buf, "Array\n"); 445 if (!(GC_FLAGS(Z_ARRVAL_P(expr)) & GC_IMMUTABLE)) { 446 if (GC_IS_RECURSIVE(Z_ARRVAL_P(expr))) { 447 smart_str_appends(buf, " *RECURSION*"); 448 return; 449 } 450 GC_PROTECT_RECURSION(Z_ARRVAL_P(expr)); 451 } 452 print_hash(buf, Z_ARRVAL_P(expr), indent, 0); 453 GC_TRY_UNPROTECT_RECURSION(Z_ARRVAL_P(expr)); 454 break; 455 case IS_OBJECT: 456 { 457 HashTable *properties; 458 459 zend_string *class_name = Z_OBJ_HANDLER_P(expr, get_class_name)(Z_OBJ_P(expr)); 460 smart_str_appends(buf, ZSTR_VAL(class_name)); 461 zend_string_release_ex(class_name, 0); 462 463 smart_str_appends(buf, " Object\n"); 464 if (GC_IS_RECURSIVE(Z_OBJ_P(expr))) { 465 smart_str_appends(buf, " *RECURSION*"); 466 return; 467 } 468 469 if ((properties = zend_get_properties_for(expr, ZEND_PROP_PURPOSE_DEBUG)) == NULL) { 470 break; 471 } 472 473 GC_PROTECT_RECURSION(Z_OBJ_P(expr)); 474 print_hash(buf, properties, indent, 1); 475 GC_UNPROTECT_RECURSION(Z_OBJ_P(expr)); 476 477 zend_release_properties(properties); 478 break; 479 } 480 case IS_LONG: 481 smart_str_append_long(buf, Z_LVAL_P(expr)); 482 break; 483 case IS_REFERENCE: 484 zend_print_zval_r_to_buf(buf, Z_REFVAL_P(expr), indent); 485 break; 486 case IS_STRING: 487 smart_str_append(buf, Z_STR_P(expr)); 488 break; 489 default: 490 { 491 zend_string *str = zval_get_string_func(expr); 492 smart_str_append(buf, str); 493 zend_string_release_ex(str, 0); 494 } 495 break; 496 } 497 } 498 /* }}} */ 499 500 ZEND_API zend_string *zend_print_zval_r_to_str(zval *expr, int indent) /* {{{ */ 501 { 502 smart_str buf = {0}; 503 zend_print_zval_r_to_buf(&buf, expr, indent); 504 smart_str_0(&buf); 505 return buf.s; 506 } 507 /* }}} */ 508 509 ZEND_API void zend_print_zval_r(zval *expr, int indent) /* {{{ */ 510 { 511 zend_string *str = zend_print_zval_r_to_str(expr, indent); 512 zend_write(ZSTR_VAL(str), ZSTR_LEN(str)); 513 zend_string_release_ex(str, 0); 514 } 515 /* }}} */ 516 517 static FILE *zend_fopen_wrapper(const char *filename, zend_string **opened_path) /* {{{ */ 518 { 519 if (opened_path) { 520 *opened_path = zend_string_init(filename, strlen(filename), 0); 521 } 522 return fopen(filename, "rb"); 523 } 524 /* }}} */ 525 526 #ifdef ZTS 527 static zend_bool short_tags_default = 1; 528 static uint32_t compiler_options_default = ZEND_COMPILE_DEFAULT; 529 #else 530 # define short_tags_default 1 531 # define compiler_options_default ZEND_COMPILE_DEFAULT 532 #endif 533 534 static void zend_set_default_compile_time_values(void) /* {{{ */ 535 { 536 /* default compile-time values */ 537 CG(short_tags) = short_tags_default; 538 CG(compiler_options) = compiler_options_default; 539 540 CG(rtd_key_counter) = 0; 541 } 542 /* }}} */ 543 544 #ifdef ZEND_WIN32 545 static void zend_get_windows_version_info(OSVERSIONINFOEX *osvi) /* {{{ */ 546 { 547 ZeroMemory(osvi, sizeof(OSVERSIONINFOEX)); 548 osvi->dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); 549 if(!GetVersionEx((OSVERSIONINFO *) osvi)) { 550 ZEND_UNREACHABLE(); /* Should not happen as sizeof is used. */ 551 } 552 } 553 /* }}} */ 554 #endif 555 556 static void zend_init_exception_op(void) /* {{{ */ 557 { 558 memset(EG(exception_op), 0, sizeof(EG(exception_op))); 559 EG(exception_op)[0].opcode = ZEND_HANDLE_EXCEPTION; 560 ZEND_VM_SET_OPCODE_HANDLER(EG(exception_op)); 561 EG(exception_op)[1].opcode = ZEND_HANDLE_EXCEPTION; 562 ZEND_VM_SET_OPCODE_HANDLER(EG(exception_op)+1); 563 EG(exception_op)[2].opcode = ZEND_HANDLE_EXCEPTION; 564 ZEND_VM_SET_OPCODE_HANDLER(EG(exception_op)+2); 565 } 566 /* }}} */ 567 568 static void zend_init_call_trampoline_op(void) /* {{{ */ 569 { 570 memset(&EG(call_trampoline_op), 0, sizeof(EG(call_trampoline_op))); 571 EG(call_trampoline_op).opcode = ZEND_CALL_TRAMPOLINE; 572 ZEND_VM_SET_OPCODE_HANDLER(&EG(call_trampoline_op)); 573 } 574 /* }}} */ 575 576 static void auto_global_dtor(zval *zv) /* {{{ */ 577 { 578 free(Z_PTR_P(zv)); 579 } 580 /* }}} */ 581 582 #ifdef ZTS 583 static void function_copy_ctor(zval *zv) /* {{{ */ 584 { 585 zend_function *old_func = Z_FUNC_P(zv); 586 zend_function *func; 587 588 if (old_func->type == ZEND_USER_FUNCTION) { 589 ZEND_ASSERT(old_func->op_array.fn_flags & ZEND_ACC_IMMUTABLE); 590 return; 591 } 592 func = pemalloc(sizeof(zend_internal_function), 1); 593 Z_FUNC_P(zv) = func; 594 memcpy(func, old_func, sizeof(zend_internal_function)); 595 function_add_ref(func); 596 if ((old_func->common.fn_flags & (ZEND_ACC_HAS_RETURN_TYPE|ZEND_ACC_HAS_TYPE_HINTS)) 597 && old_func->common.arg_info) { 598 uint32_t i; 599 uint32_t num_args = old_func->common.num_args + 1; 600 zend_arg_info *arg_info = old_func->common.arg_info - 1; 601 zend_arg_info *new_arg_info; 602 603 if (old_func->common.fn_flags & ZEND_ACC_VARIADIC) { 604 num_args++; 605 } 606 new_arg_info = pemalloc(sizeof(zend_arg_info) * num_args, 1); 607 memcpy(new_arg_info, arg_info, sizeof(zend_arg_info) * num_args); 608 for (i = 0 ; i < num_args; i++) { 609 if (ZEND_TYPE_HAS_LIST(arg_info[i].type)) { 610 zend_type_list *old_list = ZEND_TYPE_LIST(arg_info[i].type); 611 zend_type_list *new_list = pemalloc(ZEND_TYPE_LIST_SIZE(old_list->num_types), 1); 612 memcpy(new_list, old_list, ZEND_TYPE_LIST_SIZE(old_list->num_types)); 613 ZEND_TYPE_SET_PTR(new_arg_info[i].type, new_list); 614 615 zend_type *list_type; 616 ZEND_TYPE_LIST_FOREACH(new_list, list_type) { 617 zend_string *name = zend_string_dup(ZEND_TYPE_NAME(*list_type), 1); 618 ZEND_TYPE_SET_PTR(*list_type, name); 619 } ZEND_TYPE_LIST_FOREACH_END(); 620 } else if (ZEND_TYPE_HAS_NAME(arg_info[i].type)) { 621 zend_string *name = zend_string_dup(ZEND_TYPE_NAME(arg_info[i].type), 1); 622 ZEND_TYPE_SET_PTR(new_arg_info[i].type, name); 623 } 624 } 625 func->common.arg_info = new_arg_info + 1; 626 } 627 } 628 /* }}} */ 629 630 static void auto_global_copy_ctor(zval *zv) /* {{{ */ 631 { 632 zend_auto_global *old_ag = (zend_auto_global *) Z_PTR_P(zv); 633 zend_auto_global *new_ag = pemalloc(sizeof(zend_auto_global), 1); 634 635 new_ag->name = old_ag->name; 636 new_ag->auto_global_callback = old_ag->auto_global_callback; 637 new_ag->jit = old_ag->jit; 638 639 Z_PTR_P(zv) = new_ag; 640 } 641 /* }}} */ 642 643 static void compiler_globals_ctor(zend_compiler_globals *compiler_globals) /* {{{ */ 644 { 645 compiler_globals->compiled_filename = NULL; 646 647 compiler_globals->function_table = (HashTable *) malloc(sizeof(HashTable)); 648 zend_hash_init(compiler_globals->function_table, 1024, NULL, ZEND_FUNCTION_DTOR, 1); 649 zend_hash_copy(compiler_globals->function_table, global_function_table, function_copy_ctor); 650 651 compiler_globals->class_table = (HashTable *) malloc(sizeof(HashTable)); 652 zend_hash_init(compiler_globals->class_table, 64, NULL, ZEND_CLASS_DTOR, 1); 653 zend_hash_copy(compiler_globals->class_table, global_class_table, zend_class_add_ref); 654 655 zend_set_default_compile_time_values(); 656 657 compiler_globals->auto_globals = (HashTable *) malloc(sizeof(HashTable)); 658 zend_hash_init(compiler_globals->auto_globals, 8, NULL, auto_global_dtor, 1); 659 zend_hash_copy(compiler_globals->auto_globals, global_auto_globals_table, auto_global_copy_ctor); 660 661 compiler_globals->script_encoding_list = NULL; 662 663 #if ZEND_MAP_PTR_KIND == ZEND_MAP_PTR_KIND_PTR_OR_OFFSET 664 /* Map region is going to be created and resized at run-time. */ 665 ZEND_MAP_PTR_SET_REAL_BASE(compiler_globals->map_ptr_base, NULL); 666 compiler_globals->map_ptr_size = 0; 667 compiler_globals->map_ptr_last = global_map_ptr_last; 668 if (compiler_globals->map_ptr_last) { 669 /* Allocate map_ptr table */ 670 void *base; 671 compiler_globals->map_ptr_size = ZEND_MM_ALIGNED_SIZE_EX(compiler_globals->map_ptr_last, 4096); 672 base = pemalloc(compiler_globals->map_ptr_size * sizeof(void*), 1); 673 ZEND_MAP_PTR_SET_REAL_BASE(compiler_globals->map_ptr_base, base); 674 memset(base, 0, compiler_globals->map_ptr_last * sizeof(void*)); 675 } 676 #else 677 # error "Unknown ZEND_MAP_PTR_KIND" 678 #endif 679 } 680 /* }}} */ 681 682 static void compiler_globals_dtor(zend_compiler_globals *compiler_globals) /* {{{ */ 683 { 684 if (compiler_globals->function_table != GLOBAL_FUNCTION_TABLE) { 685 zend_hash_destroy(compiler_globals->function_table); 686 free(compiler_globals->function_table); 687 } 688 if (compiler_globals->class_table != GLOBAL_CLASS_TABLE) { 689 zend_hash_destroy(compiler_globals->class_table); 690 free(compiler_globals->class_table); 691 } 692 if (compiler_globals->auto_globals != GLOBAL_AUTO_GLOBALS_TABLE) { 693 zend_hash_destroy(compiler_globals->auto_globals); 694 free(compiler_globals->auto_globals); 695 } 696 if (compiler_globals->script_encoding_list) { 697 pefree((char*)compiler_globals->script_encoding_list, 1); 698 } 699 if (ZEND_MAP_PTR_REAL_BASE(compiler_globals->map_ptr_base)) { 700 free(ZEND_MAP_PTR_REAL_BASE(compiler_globals->map_ptr_base)); 701 ZEND_MAP_PTR_SET_REAL_BASE(compiler_globals->map_ptr_base, NULL); 702 compiler_globals->map_ptr_size = 0; 703 } 704 } 705 /* }}} */ 706 707 static void executor_globals_ctor(zend_executor_globals *executor_globals) /* {{{ */ 708 { 709 zend_startup_constants(); 710 zend_copy_constants(executor_globals->zend_constants, GLOBAL_CONSTANTS_TABLE); 711 zend_init_rsrc_plist(); 712 zend_init_exception_op(); 713 zend_init_call_trampoline_op(); 714 memset(&executor_globals->trampoline, 0, sizeof(zend_op_array)); 715 executor_globals->lambda_count = 0; 716 ZVAL_UNDEF(&executor_globals->user_error_handler); 717 ZVAL_UNDEF(&executor_globals->user_exception_handler); 718 executor_globals->in_autoload = NULL; 719 executor_globals->current_execute_data = NULL; 720 executor_globals->current_module = NULL; 721 executor_globals->exit_status = 0; 722 #if XPFPA_HAVE_CW 723 executor_globals->saved_fpu_cw = 0; 724 #endif 725 executor_globals->saved_fpu_cw_ptr = NULL; 726 executor_globals->active = 0; 727 executor_globals->bailout = NULL; 728 executor_globals->error_handling = EH_NORMAL; 729 executor_globals->exception_class = NULL; 730 executor_globals->exception = NULL; 731 executor_globals->objects_store.object_buckets = NULL; 732 #ifdef ZEND_WIN32 733 zend_get_windows_version_info(&executor_globals->windows_version_info); 734 #endif 735 executor_globals->flags = EG_FLAGS_INITIAL; 736 } 737 /* }}} */ 738 739 static void executor_globals_dtor(zend_executor_globals *executor_globals) /* {{{ */ 740 { 741 zend_ini_dtor(executor_globals->ini_directives); 742 743 if (&executor_globals->persistent_list != global_persistent_list) { 744 zend_destroy_rsrc_list(&executor_globals->persistent_list); 745 } 746 if (executor_globals->zend_constants != GLOBAL_CONSTANTS_TABLE) { 747 zend_hash_destroy(executor_globals->zend_constants); 748 free(executor_globals->zend_constants); 749 } 750 } 751 /* }}} */ 752 753 static void zend_new_thread_end_handler(THREAD_T thread_id) /* {{{ */ 754 { 755 zend_copy_ini_directives(); 756 zend_ini_refresh_caches(ZEND_INI_STAGE_STARTUP); 757 } 758 /* }}} */ 759 #endif 760 761 #if defined(__FreeBSD__) || defined(__DragonFly__) 762 /* FreeBSD and DragonFly floating point precision fix */ 763 #include <floatingpoint.h> 764 #endif 765 766 static void ini_scanner_globals_ctor(zend_ini_scanner_globals *scanner_globals_p) /* {{{ */ 767 { 768 memset(scanner_globals_p, 0, sizeof(*scanner_globals_p)); 769 } 770 /* }}} */ 771 772 static void php_scanner_globals_ctor(zend_php_scanner_globals *scanner_globals_p) /* {{{ */ 773 { 774 memset(scanner_globals_p, 0, sizeof(*scanner_globals_p)); 775 } 776 /* }}} */ 777 778 static void module_destructor_zval(zval *zv) /* {{{ */ 779 { 780 zend_module_entry *module = (zend_module_entry*)Z_PTR_P(zv); 781 782 module_destructor(module); 783 free(module); 784 } 785 /* }}} */ 786 787 static zend_bool php_auto_globals_create_globals(zend_string *name) /* {{{ */ 788 { 789 zval globals; 790 791 /* IS_ARRAY, but with ref-counter 1 and not IS_TYPE_REFCOUNTED */ 792 ZVAL_ARR(&globals, &EG(symbol_table)); 793 Z_TYPE_FLAGS_P(&globals) = 0; 794 ZVAL_NEW_REF(&globals, &globals); 795 zend_hash_update(&EG(symbol_table), name, &globals); 796 return 0; 797 } 798 /* }}} */ 799 800 void zend_startup(zend_utility_functions *utility_functions) /* {{{ */ 801 { 802 #ifdef ZTS 803 zend_compiler_globals *compiler_globals; 804 zend_executor_globals *executor_globals; 805 extern ZEND_API ts_rsrc_id ini_scanner_globals_id; 806 extern ZEND_API ts_rsrc_id language_scanner_globals_id; 807 #else 808 extern zend_ini_scanner_globals ini_scanner_globals; 809 extern zend_php_scanner_globals language_scanner_globals; 810 #endif 811 812 zend_cpu_startup(); 813 814 #ifdef ZEND_WIN32 815 php_win32_cp_set_by_id(65001); 816 #endif 817 818 start_memory_manager(); 819 820 virtual_cwd_startup(); /* Could use shutdown to free the main cwd but it would just slow it down for CGI */ 821 822 #if defined(__FreeBSD__) || defined(__DragonFly__) 823 /* FreeBSD and DragonFly floating point precision fix */ 824 fpsetmask(0); 825 #endif 826 827 zend_startup_strtod(); 828 zend_startup_extensions_mechanism(); 829 830 /* Set up utility functions and values */ 831 zend_error_cb = utility_functions->error_function; 832 zend_printf = utility_functions->printf_function; 833 zend_write = utility_functions->write_function; 834 zend_fopen = utility_functions->fopen_function; 835 if (!zend_fopen) { 836 zend_fopen = zend_fopen_wrapper; 837 } 838 zend_stream_open_function = utility_functions->stream_open_function; 839 zend_message_dispatcher_p = utility_functions->message_handler; 840 zend_get_configuration_directive_p = utility_functions->get_configuration_directive; 841 zend_ticks_function = utility_functions->ticks_function; 842 zend_on_timeout = utility_functions->on_timeout; 843 zend_printf_to_smart_string = utility_functions->printf_to_smart_string_function; 844 zend_printf_to_smart_str = utility_functions->printf_to_smart_str_function; 845 zend_getenv = utility_functions->getenv_function; 846 zend_resolve_path = utility_functions->resolve_path_function; 847 848 zend_interrupt_function = NULL; 849 850 #ifdef HAVE_DTRACE 851 /* build with dtrace support */ 852 { 853 char *tmp = getenv("USE_ZEND_DTRACE"); 854 855 if (tmp && zend_atoi(tmp, 0)) { 856 zend_dtrace_enabled = 1; 857 zend_compile_file = dtrace_compile_file; 858 zend_execute_ex = dtrace_execute_ex; 859 zend_execute_internal = dtrace_execute_internal; 860 861 zend_observer_error_register(dtrace_error_notify_cb); 862 } else { 863 zend_compile_file = compile_file; 864 zend_execute_ex = execute_ex; 865 zend_execute_internal = NULL; 866 } 867 } 868 #else 869 zend_compile_file = compile_file; 870 zend_execute_ex = execute_ex; 871 zend_execute_internal = NULL; 872 #endif /* HAVE_DTRACE */ 873 zend_compile_string = compile_string; 874 zend_throw_exception_hook = NULL; 875 876 /* Set up the default garbage collection implementation. */ 877 gc_collect_cycles = zend_gc_collect_cycles; 878 879 zend_vm_init(); 880 881 /* set up version */ 882 zend_version_info = strdup(ZEND_CORE_VERSION_INFO); 883 zend_version_info_length = sizeof(ZEND_CORE_VERSION_INFO) - 1; 884 885 GLOBAL_FUNCTION_TABLE = (HashTable *) malloc(sizeof(HashTable)); 886 GLOBAL_CLASS_TABLE = (HashTable *) malloc(sizeof(HashTable)); 887 GLOBAL_AUTO_GLOBALS_TABLE = (HashTable *) malloc(sizeof(HashTable)); 888 GLOBAL_CONSTANTS_TABLE = (HashTable *) malloc(sizeof(HashTable)); 889 890 zend_hash_init(GLOBAL_FUNCTION_TABLE, 1024, NULL, ZEND_FUNCTION_DTOR, 1); 891 zend_hash_init(GLOBAL_CLASS_TABLE, 64, NULL, ZEND_CLASS_DTOR, 1); 892 zend_hash_init(GLOBAL_AUTO_GLOBALS_TABLE, 8, NULL, auto_global_dtor, 1); 893 zend_hash_init(GLOBAL_CONSTANTS_TABLE, 128, NULL, ZEND_CONSTANT_DTOR, 1); 894 895 zend_hash_init(&module_registry, 32, NULL, module_destructor_zval, 1); 896 zend_init_rsrc_list_dtors(); 897 898 #ifdef ZTS 899 ts_allocate_fast_id(&compiler_globals_id, &compiler_globals_offset, sizeof(zend_compiler_globals), (ts_allocate_ctor) compiler_globals_ctor, (ts_allocate_dtor) compiler_globals_dtor); 900 ts_allocate_fast_id(&executor_globals_id, &executor_globals_offset, sizeof(zend_executor_globals), (ts_allocate_ctor) executor_globals_ctor, (ts_allocate_dtor) executor_globals_dtor); 901 ts_allocate_fast_id(&language_scanner_globals_id, &language_scanner_globals_offset, sizeof(zend_php_scanner_globals), (ts_allocate_ctor) php_scanner_globals_ctor, NULL); 902 ts_allocate_fast_id(&ini_scanner_globals_id, &ini_scanner_globals_offset, sizeof(zend_ini_scanner_globals), (ts_allocate_ctor) ini_scanner_globals_ctor, NULL); 903 compiler_globals = ts_resource(compiler_globals_id); 904 executor_globals = ts_resource(executor_globals_id); 905 906 compiler_globals_dtor(compiler_globals); 907 compiler_globals->in_compilation = 0; 908 compiler_globals->function_table = (HashTable *) malloc(sizeof(HashTable)); 909 compiler_globals->class_table = (HashTable *) malloc(sizeof(HashTable)); 910 911 *compiler_globals->function_table = *GLOBAL_FUNCTION_TABLE; 912 *compiler_globals->class_table = *GLOBAL_CLASS_TABLE; 913 compiler_globals->auto_globals = GLOBAL_AUTO_GLOBALS_TABLE; 914 915 zend_hash_destroy(executor_globals->zend_constants); 916 *executor_globals->zend_constants = *GLOBAL_CONSTANTS_TABLE; 917 #else 918 ini_scanner_globals_ctor(&ini_scanner_globals); 919 php_scanner_globals_ctor(&language_scanner_globals); 920 zend_set_default_compile_time_values(); 921 #ifdef ZEND_WIN32 922 zend_get_windows_version_info(&EG(windows_version_info)); 923 #endif 924 # if ZEND_MAP_PTR_KIND == ZEND_MAP_PTR_KIND_PTR 925 /* Create a map region, used for indirect pointers from shared to 926 * process memory. It's allocatred once and never resized. 927 * All processes must map it into the same address space. 928 */ 929 CG(map_ptr_size) = 1024 * 1024; // TODO: initial size ??? 930 CG(map_ptr_last) = 0; 931 ZEND_MAP_PTR_SET_REAL_BASE(CG(map_ptr_base), pemalloc(CG(map_ptr_size) * sizeof(void*), 1)); 932 # elif ZEND_MAP_PTR_KIND == ZEND_MAP_PTR_KIND_PTR_OR_OFFSET 933 /* Map region is going to be created and resized at run-time. */ 934 ZEND_MAP_PTR_SET_REAL_BASE(CG(map_ptr_base), NULL); 935 CG(map_ptr_size) = 0; 936 CG(map_ptr_last) = 0; 937 # else 938 # error "Unknown ZEND_MAP_PTR_KIND" 939 # endif 940 #endif 941 EG(error_reporting) = E_ALL & ~E_NOTICE; 942 943 zend_interned_strings_init(); 944 zend_startup_builtin_functions(); 945 zend_register_standard_constants(); 946 zend_register_auto_global(zend_string_init_interned("GLOBALS", sizeof("GLOBALS") - 1, 1), 1, php_auto_globals_create_globals); 947 948 #ifndef ZTS 949 zend_init_rsrc_plist(); 950 zend_init_exception_op(); 951 zend_init_call_trampoline_op(); 952 #endif 953 954 zend_ini_startup(); 955 956 #ifdef ZEND_WIN32 957 /* Uses INI settings, so needs to be run after it. */ 958 php_win32_cp_setup(); 959 #endif 960 961 #ifdef ZTS 962 tsrm_set_new_thread_end_handler(zend_new_thread_end_handler); 963 tsrm_set_shutdown_handler(zend_interned_strings_dtor); 964 #endif 965 } 966 /* }}} */ 967 968 void zend_register_standard_ini_entries(void) /* {{{ */ 969 { 970 int module_number = 0; 971 972 REGISTER_INI_ENTRIES(); 973 } 974 /* }}} */ 975 976 static zend_class_entry *resolve_type_name(zend_string *type_name) { 977 zend_string *lc_type_name = zend_string_tolower(type_name); 978 zend_class_entry *ce = zend_hash_find_ptr(CG(class_table), lc_type_name); 979 980 ZEND_ASSERT(ce && ce->type == ZEND_INTERNAL_CLASS); 981 zend_string_release(lc_type_name); 982 return ce; 983 } 984 985 static void zend_resolve_property_types(void) /* {{{ */ 986 { 987 zend_class_entry *ce; 988 zend_property_info *prop_info; 989 990 ZEND_HASH_FOREACH_PTR(CG(class_table), ce) { 991 if (ce->type != ZEND_INTERNAL_CLASS) { 992 continue; 993 } 994 995 if (UNEXPECTED(ZEND_CLASS_HAS_TYPE_HINTS(ce))) { 996 ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop_info) { 997 zend_type *single_type; 998 ZEND_TYPE_FOREACH(prop_info->type, single_type) { 999 if (ZEND_TYPE_HAS_NAME(*single_type)) { 1000 zend_string *type_name = ZEND_TYPE_NAME(*single_type); 1001 ZEND_TYPE_SET_CE(*single_type, resolve_type_name(type_name)); 1002 zend_string_release(type_name); 1003 } 1004 } ZEND_TYPE_FOREACH_END(); 1005 } ZEND_HASH_FOREACH_END(); 1006 } 1007 ce->ce_flags |= ZEND_ACC_PROPERTY_TYPES_RESOLVED; 1008 } ZEND_HASH_FOREACH_END(); 1009 } 1010 /* }}} */ 1011 1012 /* Unlink the global (r/o) copies of the class, function and constant tables, 1013 * and use a fresh r/w copy for the startup thread 1014 */ 1015 zend_result zend_post_startup(void) /* {{{ */ 1016 { 1017 #ifdef ZTS 1018 zend_encoding **script_encoding_list; 1019 1020 zend_compiler_globals *compiler_globals = ts_resource(compiler_globals_id); 1021 zend_executor_globals *executor_globals = ts_resource(executor_globals_id); 1022 #endif 1023 1024 zend_resolve_property_types(); 1025 1026 if (zend_post_startup_cb) { 1027 zend_result (*cb)(void) = zend_post_startup_cb; 1028 1029 zend_post_startup_cb = NULL; 1030 if (cb() != SUCCESS) { 1031 return FAILURE; 1032 } 1033 } 1034 1035 #ifdef ZTS 1036 *GLOBAL_FUNCTION_TABLE = *compiler_globals->function_table; 1037 *GLOBAL_CLASS_TABLE = *compiler_globals->class_table; 1038 *GLOBAL_CONSTANTS_TABLE = *executor_globals->zend_constants; 1039 global_map_ptr_last = compiler_globals->map_ptr_last; 1040 1041 short_tags_default = CG(short_tags); 1042 compiler_options_default = CG(compiler_options); 1043 1044 zend_destroy_rsrc_list(&EG(persistent_list)); 1045 free(compiler_globals->function_table); 1046 compiler_globals->function_table = NULL; 1047 free(compiler_globals->class_table); 1048 compiler_globals->class_table = NULL; 1049 if (ZEND_MAP_PTR_REAL_BASE(compiler_globals->map_ptr_base)) { 1050 free(ZEND_MAP_PTR_REAL_BASE(compiler_globals->map_ptr_base)); 1051 } 1052 ZEND_MAP_PTR_SET_REAL_BASE(compiler_globals->map_ptr_base, NULL); 1053 if ((script_encoding_list = (zend_encoding **)compiler_globals->script_encoding_list)) { 1054 compiler_globals_ctor(compiler_globals); 1055 compiler_globals->script_encoding_list = (const zend_encoding **)script_encoding_list; 1056 } else { 1057 compiler_globals_ctor(compiler_globals); 1058 } 1059 free(EG(zend_constants)); 1060 EG(zend_constants) = NULL; 1061 1062 executor_globals_ctor(executor_globals); 1063 global_persistent_list = &EG(persistent_list); 1064 zend_copy_ini_directives(); 1065 #else 1066 global_map_ptr_last = CG(map_ptr_last); 1067 #endif 1068 1069 return SUCCESS; 1070 } 1071 /* }}} */ 1072 1073 void zend_shutdown(void) /* {{{ */ 1074 { 1075 zend_vm_dtor(); 1076 1077 zend_destroy_rsrc_list(&EG(persistent_list)); 1078 zend_destroy_modules(); 1079 1080 virtual_cwd_deactivate(); 1081 virtual_cwd_shutdown(); 1082 1083 zend_hash_destroy(GLOBAL_FUNCTION_TABLE); 1084 zend_hash_destroy(GLOBAL_CLASS_TABLE); 1085 1086 zend_hash_destroy(GLOBAL_AUTO_GLOBALS_TABLE); 1087 free(GLOBAL_AUTO_GLOBALS_TABLE); 1088 1089 zend_shutdown_extensions(); 1090 free(zend_version_info); 1091 1092 free(GLOBAL_FUNCTION_TABLE); 1093 free(GLOBAL_CLASS_TABLE); 1094 1095 zend_hash_destroy(GLOBAL_CONSTANTS_TABLE); 1096 free(GLOBAL_CONSTANTS_TABLE); 1097 zend_shutdown_strtod(); 1098 zend_attributes_shutdown(); 1099 1100 #ifdef ZTS 1101 GLOBAL_FUNCTION_TABLE = NULL; 1102 GLOBAL_CLASS_TABLE = NULL; 1103 GLOBAL_AUTO_GLOBALS_TABLE = NULL; 1104 GLOBAL_CONSTANTS_TABLE = NULL; 1105 ts_free_id(executor_globals_id); 1106 ts_free_id(compiler_globals_id); 1107 #else 1108 if (ZEND_MAP_PTR_REAL_BASE(CG(map_ptr_base))) { 1109 free(ZEND_MAP_PTR_REAL_BASE(CG(map_ptr_base))); 1110 ZEND_MAP_PTR_SET_REAL_BASE(CG(map_ptr_base), NULL); 1111 CG(map_ptr_size) = 0; 1112 } 1113 if (CG(script_encoding_list)) { 1114 free(ZEND_VOIDP(CG(script_encoding_list))); 1115 CG(script_encoding_list) = NULL; 1116 CG(script_encoding_list_size) = 0; 1117 } 1118 #endif 1119 zend_destroy_rsrc_list_dtors(); 1120 } 1121 /* }}} */ 1122 1123 void zend_set_utility_values(zend_utility_values *utility_values) /* {{{ */ 1124 { 1125 zend_uv = *utility_values; 1126 } 1127 /* }}} */ 1128 1129 /* this should be compatible with the standard zenderror */ 1130 ZEND_COLD void zenderror(const char *error) /* {{{ */ 1131 { 1132 CG(parse_error) = 0; 1133 1134 if (EG(exception)) { 1135 /* An exception was thrown in the lexer, don't throw another in the parser. */ 1136 return; 1137 } 1138 1139 zend_throw_exception(zend_ce_parse_error, error, 0); 1140 } 1141 /* }}} */ 1142 1143 BEGIN_EXTERN_C() 1144 ZEND_API ZEND_COLD ZEND_NORETURN void _zend_bailout(const char *filename, uint32_t lineno) /* {{{ */ 1145 { 1146 1147 if (!EG(bailout)) { 1148 zend_output_debug_string(1, "%s(%d) : Bailed out without a bailout address!", filename, lineno); 1149 exit(-1); 1150 } 1151 gc_protect(1); 1152 CG(unclean_shutdown) = 1; 1153 CG(active_class_entry) = NULL; 1154 CG(in_compilation) = 0; 1155 EG(current_execute_data) = NULL; 1156 LONGJMP(*EG(bailout), FAILURE); 1157 } 1158 /* }}} */ 1159 END_EXTERN_C() 1160 1161 ZEND_API void zend_append_version_info(const zend_extension *extension) /* {{{ */ 1162 { 1163 char *new_info; 1164 uint32_t new_info_length; 1165 1166 new_info_length = (uint32_t)(sizeof(" with v, , by \n") 1167 + strlen(extension->name) 1168 + strlen(extension->version) 1169 + strlen(extension->copyright) 1170 + strlen(extension->author)); 1171 1172 new_info = (char *) malloc(new_info_length + 1); 1173 1174 snprintf(new_info, new_info_length, " with %s v%s, %s, by %s\n", extension->name, extension->version, extension->copyright, extension->author); 1175 1176 zend_version_info = (char *) realloc(zend_version_info, zend_version_info_length+new_info_length + 1); 1177 strncat(zend_version_info, new_info, new_info_length); 1178 zend_version_info_length += new_info_length; 1179 free(new_info); 1180 } 1181 /* }}} */ 1182 1183 ZEND_API const char *get_zend_version(void) /* {{{ */ 1184 { 1185 return zend_version_info; 1186 } 1187 /* }}} */ 1188 1189 ZEND_API void zend_activate(void) /* {{{ */ 1190 { 1191 #ifdef ZTS 1192 virtual_cwd_activate(); 1193 #endif 1194 gc_reset(); 1195 init_compiler(); 1196 init_executor(); 1197 startup_scanner(); 1198 if (CG(map_ptr_last)) { 1199 memset(ZEND_MAP_PTR_REAL_BASE(CG(map_ptr_base)), 0, CG(map_ptr_last) * sizeof(void*)); 1200 } 1201 zend_observer_activate(); 1202 } 1203 /* }}} */ 1204 1205 void zend_call_destructors(void) /* {{{ */ 1206 { 1207 zend_try { 1208 shutdown_destructors(); 1209 } zend_end_try(); 1210 } 1211 /* }}} */ 1212 1213 ZEND_API void zend_deactivate(void) /* {{{ */ 1214 { 1215 /* we're no longer executing anything */ 1216 EG(current_execute_data) = NULL; 1217 1218 zend_observer_deactivate(); 1219 1220 zend_try { 1221 shutdown_scanner(); 1222 } zend_end_try(); 1223 1224 /* shutdown_executor() takes care of its own bailout handling */ 1225 shutdown_executor(); 1226 1227 zend_try { 1228 zend_ini_deactivate(); 1229 } zend_end_try(); 1230 1231 zend_try { 1232 shutdown_compiler(); 1233 } zend_end_try(); 1234 1235 zend_destroy_rsrc_list(&EG(regular_list)); 1236 1237 #if GC_BENCH 1238 fprintf(stderr, "GC Statistics\n"); 1239 fprintf(stderr, "-------------\n"); 1240 fprintf(stderr, "Runs: %d\n", GC_G(gc_runs)); 1241 fprintf(stderr, "Collected: %d\n", GC_G(collected)); 1242 fprintf(stderr, "Root buffer length: %d\n", GC_G(root_buf_length)); 1243 fprintf(stderr, "Root buffer peak: %d\n\n", GC_G(root_buf_peak)); 1244 fprintf(stderr, " Possible Remove from Marked\n"); 1245 fprintf(stderr, " Root Buffered buffer grey\n"); 1246 fprintf(stderr, " -------- -------- ----------- ------\n"); 1247 fprintf(stderr, "ZVAL %8d %8d %9d %8d\n", GC_G(zval_possible_root), GC_G(zval_buffered), GC_G(zval_remove_from_buffer), GC_G(zval_marked_grey)); 1248 #endif 1249 } 1250 /* }}} */ 1251 1252 BEGIN_EXTERN_C() 1253 ZEND_API void zend_message_dispatcher(zend_long message, const void *data) /* {{{ */ 1254 { 1255 if (zend_message_dispatcher_p) { 1256 zend_message_dispatcher_p(message, data); 1257 } 1258 } 1259 /* }}} */ 1260 END_EXTERN_C() 1261 1262 ZEND_API zval *zend_get_configuration_directive(zend_string *name) /* {{{ */ 1263 { 1264 if (zend_get_configuration_directive_p) { 1265 return zend_get_configuration_directive_p(name); 1266 } else { 1267 return NULL; 1268 } 1269 } 1270 /* }}} */ 1271 1272 #define SAVE_STACK(stack) do { \ 1273 if (CG(stack).top) { \ 1274 memcpy(&stack, &CG(stack), sizeof(zend_stack)); \ 1275 CG(stack).top = CG(stack).max = 0; \ 1276 CG(stack).elements = NULL; \ 1277 } else { \ 1278 stack.top = 0; \ 1279 } \ 1280 } while (0) 1281 1282 #define RESTORE_STACK(stack) do { \ 1283 if (stack.top) { \ 1284 zend_stack_destroy(&CG(stack)); \ 1285 memcpy(&CG(stack), &stack, sizeof(zend_stack)); \ 1286 } \ 1287 } while (0) 1288 1289 static ZEND_COLD void zend_error_impl( 1290 int orig_type, const char *error_filename, uint32_t error_lineno, zend_string *message) 1291 { 1292 zval params[4]; 1293 zval retval; 1294 zval orig_user_error_handler; 1295 zend_bool in_compilation; 1296 zend_class_entry *saved_class_entry; 1297 zend_stack loop_var_stack; 1298 zend_stack delayed_oplines_stack; 1299 int type = orig_type & E_ALL; 1300 1301 /* Report about uncaught exception in case of fatal errors */ 1302 if (EG(exception)) { 1303 zend_execute_data *ex; 1304 const zend_op *opline; 1305 1306 if (type & E_FATAL_ERRORS) { 1307 ex = EG(current_execute_data); 1308 opline = NULL; 1309 while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) { 1310 ex = ex->prev_execute_data; 1311 } 1312 if (ex && ex->opline->opcode == ZEND_HANDLE_EXCEPTION && 1313 EG(opline_before_exception)) { 1314 opline = EG(opline_before_exception); 1315 } 1316 zend_exception_error(EG(exception), E_WARNING); 1317 EG(exception) = NULL; 1318 if (opline) { 1319 ex->opline = opline; 1320 } 1321 } 1322 } 1323 1324 zend_observer_error_notify(type, error_filename, error_lineno, message); 1325 1326 /* if we don't have a user defined error handler */ 1327 if (Z_TYPE(EG(user_error_handler)) == IS_UNDEF 1328 || !(EG(user_error_handler_error_reporting) & type) 1329 || EG(error_handling) != EH_NORMAL) { 1330 zend_error_cb(orig_type, error_filename, error_lineno, message); 1331 } else switch (type) { 1332 case E_ERROR: 1333 case E_PARSE: 1334 case E_CORE_ERROR: 1335 case E_CORE_WARNING: 1336 case E_COMPILE_ERROR: 1337 case E_COMPILE_WARNING: 1338 /* The error may not be safe to handle in user-space */ 1339 zend_error_cb(orig_type, error_filename, error_lineno, message); 1340 break; 1341 default: 1342 /* Handle the error in user space */ 1343 ZVAL_STR_COPY(¶ms[1], message); 1344 ZVAL_LONG(¶ms[0], type); 1345 1346 if (error_filename) { 1347 ZVAL_STRING(¶ms[2], error_filename); 1348 } else { 1349 ZVAL_NULL(¶ms[2]); 1350 } 1351 1352 ZVAL_LONG(¶ms[3], error_lineno); 1353 1354 ZVAL_COPY_VALUE(&orig_user_error_handler, &EG(user_error_handler)); 1355 ZVAL_UNDEF(&EG(user_error_handler)); 1356 1357 /* User error handler may include() additinal PHP files. 1358 * If an error was generated during comilation PHP will compile 1359 * such scripts recursively, but some CG() variables may be 1360 * inconsistent. */ 1361 1362 in_compilation = CG(in_compilation); 1363 if (in_compilation) { 1364 saved_class_entry = CG(active_class_entry); 1365 CG(active_class_entry) = NULL; 1366 SAVE_STACK(loop_var_stack); 1367 SAVE_STACK(delayed_oplines_stack); 1368 CG(in_compilation) = 0; 1369 } 1370 1371 if (call_user_function(CG(function_table), NULL, &orig_user_error_handler, &retval, 4, params) == SUCCESS) { 1372 if (Z_TYPE(retval) != IS_UNDEF) { 1373 if (Z_TYPE(retval) == IS_FALSE) { 1374 zend_error_cb(orig_type, error_filename, error_lineno, message); 1375 } 1376 zval_ptr_dtor(&retval); 1377 } 1378 } else if (!EG(exception)) { 1379 /* The user error handler failed, use built-in error handler */ 1380 zend_error_cb(orig_type, error_filename, error_lineno, message); 1381 } 1382 1383 if (in_compilation) { 1384 CG(active_class_entry) = saved_class_entry; 1385 RESTORE_STACK(loop_var_stack); 1386 RESTORE_STACK(delayed_oplines_stack); 1387 CG(in_compilation) = 1; 1388 } 1389 1390 zval_ptr_dtor(¶ms[2]); 1391 zval_ptr_dtor(¶ms[1]); 1392 1393 if (Z_TYPE(EG(user_error_handler)) == IS_UNDEF) { 1394 ZVAL_COPY_VALUE(&EG(user_error_handler), &orig_user_error_handler); 1395 } else { 1396 zval_ptr_dtor(&orig_user_error_handler); 1397 } 1398 break; 1399 } 1400 1401 if (type == E_PARSE) { 1402 /* eval() errors do not affect exit_status */ 1403 if (!(EG(current_execute_data) && 1404 EG(current_execute_data)->func && 1405 ZEND_USER_CODE(EG(current_execute_data)->func->type) && 1406 EG(current_execute_data)->opline->opcode == ZEND_INCLUDE_OR_EVAL && 1407 EG(current_execute_data)->opline->extended_value == ZEND_EVAL)) { 1408 EG(exit_status) = 255; 1409 } 1410 } 1411 } 1412 /* }}} */ 1413 1414 static ZEND_COLD void zend_error_va_list( 1415 int orig_type, const char *error_filename, uint32_t error_lineno, 1416 const char *format, va_list args) 1417 { 1418 zend_string *message = zend_vstrpprintf(0, format, args); 1419 zend_error_impl(orig_type, error_filename, error_lineno, message); 1420 zend_string_release(message); 1421 } 1422 1423 static ZEND_COLD void get_filename_lineno(int type, const char **filename, uint32_t *lineno) { 1424 /* Obtain relevant filename and lineno */ 1425 switch (type) { 1426 case E_CORE_ERROR: 1427 case E_CORE_WARNING: 1428 *filename = NULL; 1429 *lineno = 0; 1430 break; 1431 case E_PARSE: 1432 case E_COMPILE_ERROR: 1433 case E_COMPILE_WARNING: 1434 case E_ERROR: 1435 case E_NOTICE: 1436 case E_STRICT: 1437 case E_DEPRECATED: 1438 case E_WARNING: 1439 case E_USER_ERROR: 1440 case E_USER_WARNING: 1441 case E_USER_NOTICE: 1442 case E_USER_DEPRECATED: 1443 case E_RECOVERABLE_ERROR: 1444 if (zend_is_compiling()) { 1445 *filename = ZSTR_VAL(zend_get_compiled_filename()); 1446 *lineno = zend_get_compiled_lineno(); 1447 } else if (zend_is_executing()) { 1448 *filename = zend_get_executed_filename(); 1449 if ((*filename)[0] == '[') { /* [no active file] */ 1450 *filename = NULL; 1451 *lineno = 0; 1452 } else { 1453 *lineno = zend_get_executed_lineno(); 1454 } 1455 } else { 1456 *filename = NULL; 1457 *lineno = 0; 1458 } 1459 break; 1460 default: 1461 *filename = NULL; 1462 *lineno = 0; 1463 break; 1464 } 1465 if (!*filename) { 1466 *filename = "Unknown"; 1467 } 1468 } 1469 1470 ZEND_API ZEND_COLD void zend_error_at( 1471 int type, const char *filename, uint32_t lineno, const char *format, ...) { 1472 va_list args; 1473 1474 if (!filename) { 1475 uint32_t dummy_lineno; 1476 get_filename_lineno(type, &filename, &dummy_lineno); 1477 } 1478 1479 va_start(args, format); 1480 zend_error_va_list(type, filename, lineno, format, args); 1481 va_end(args); 1482 } 1483 1484 ZEND_API ZEND_COLD void zend_error(int type, const char *format, ...) { 1485 const char *filename; 1486 uint32_t lineno; 1487 va_list args; 1488 1489 get_filename_lineno(type, &filename, &lineno); 1490 va_start(args, format); 1491 zend_error_va_list(type, filename, lineno, format, args); 1492 va_end(args); 1493 } 1494 1495 ZEND_API ZEND_COLD ZEND_NORETURN void zend_error_at_noreturn( 1496 int type, const char *filename, uint32_t lineno, const char *format, ...) 1497 { 1498 va_list args; 1499 1500 if (!filename) { 1501 uint32_t dummy_lineno; 1502 get_filename_lineno(type, &filename, &dummy_lineno); 1503 } 1504 1505 va_start(args, format); 1506 zend_error_va_list(type, filename, lineno, format, args); 1507 va_end(args); 1508 /* Should never reach this. */ 1509 abort(); 1510 } 1511 1512 ZEND_API ZEND_COLD ZEND_NORETURN void zend_error_noreturn(int type, const char *format, ...) 1513 { 1514 const char *filename; 1515 uint32_t lineno; 1516 va_list args; 1517 1518 get_filename_lineno(type, &filename, &lineno); 1519 va_start(args, format); 1520 zend_error_va_list(type, filename, lineno, format, args); 1521 va_end(args); 1522 /* Should never reach this. */ 1523 abort(); 1524 } 1525 1526 ZEND_API ZEND_COLD void zend_error_zstr(int type, zend_string *message) { 1527 const char *filename; 1528 uint32_t lineno; 1529 get_filename_lineno(type, &filename, &lineno); 1530 zend_error_impl(type, filename, lineno, message); 1531 } 1532 1533 ZEND_API ZEND_COLD void zend_throw_error(zend_class_entry *exception_ce, const char *format, ...) /* {{{ */ 1534 { 1535 va_list va; 1536 char *message = NULL; 1537 1538 if (!exception_ce) { 1539 exception_ce = zend_ce_error; 1540 } 1541 1542 /* Marker used to disable exception generation during preloading. */ 1543 if (EG(exception) == (void*)(uintptr_t)-1) { 1544 return; 1545 } 1546 1547 va_start(va, format); 1548 zend_vspprintf(&message, 0, format, va); 1549 1550 //TODO: we can't convert compile-time errors to exceptions yet??? 1551 if (EG(current_execute_data) && !CG(in_compilation)) { 1552 zend_throw_exception(exception_ce, message, 0); 1553 } else { 1554 zend_error(E_ERROR, "%s", message); 1555 } 1556 1557 efree(message); 1558 va_end(va); 1559 } 1560 /* }}} */ 1561 1562 ZEND_API ZEND_COLD void zend_type_error(const char *format, ...) /* {{{ */ 1563 { 1564 va_list va; 1565 char *message = NULL; 1566 1567 va_start(va, format); 1568 zend_vspprintf(&message, 0, format, va); 1569 zend_throw_exception(zend_ce_type_error, message, 0); 1570 efree(message); 1571 va_end(va); 1572 } /* }}} */ 1573 1574 ZEND_API ZEND_COLD void zend_argument_count_error(const char *format, ...) /* {{{ */ 1575 { 1576 va_list va; 1577 char *message = NULL; 1578 1579 va_start(va, format); 1580 zend_vspprintf(&message, 0, format, va); 1581 zend_throw_exception(zend_ce_argument_count_error, message, 0); 1582 efree(message); 1583 1584 va_end(va); 1585 } /* }}} */ 1586 1587 ZEND_API ZEND_COLD void zend_value_error(const char *format, ...) /* {{{ */ 1588 { 1589 va_list va; 1590 char *message = NULL; 1591 1592 va_start(va, format); 1593 zend_vspprintf(&message, 0, format, va); 1594 zend_throw_exception(zend_ce_value_error, message, 0); 1595 efree(message); 1596 va_end(va); 1597 } /* }}} */ 1598 1599 ZEND_API ZEND_COLD void zend_output_debug_string(zend_bool trigger_break, const char *format, ...) /* {{{ */ 1600 { 1601 #if ZEND_DEBUG 1602 va_list args; 1603 1604 va_start(args, format); 1605 # ifdef ZEND_WIN32 1606 { 1607 char output_buf[1024]; 1608 1609 vsnprintf(output_buf, 1024, format, args); 1610 OutputDebugString(output_buf); 1611 OutputDebugString("\n"); 1612 if (trigger_break && IsDebuggerPresent()) { 1613 DebugBreak(); 1614 } 1615 } 1616 # else 1617 vfprintf(stderr, format, args); 1618 fprintf(stderr, "\n"); 1619 # endif 1620 va_end(args); 1621 #endif 1622 } 1623 /* }}} */ 1624 1625 ZEND_API ZEND_COLD void zend_user_exception_handler(void) /* {{{ */ 1626 { 1627 zval orig_user_exception_handler; 1628 zval params[1], retval2; 1629 zend_object *old_exception; 1630 1631 if (zend_is_unwind_exit(EG(exception))) { 1632 return; 1633 } 1634 1635 old_exception = EG(exception); 1636 EG(exception) = NULL; 1637 ZVAL_OBJ(¶ms[0], old_exception); 1638 ZVAL_COPY_VALUE(&orig_user_exception_handler, &EG(user_exception_handler)); 1639 1640 if (call_user_function(CG(function_table), NULL, &orig_user_exception_handler, &retval2, 1, params) == SUCCESS) { 1641 zval_ptr_dtor(&retval2); 1642 if (EG(exception)) { 1643 OBJ_RELEASE(EG(exception)); 1644 EG(exception) = NULL; 1645 } 1646 OBJ_RELEASE(old_exception); 1647 } else { 1648 EG(exception) = old_exception; 1649 } 1650 } /* }}} */ 1651 1652 ZEND_API zend_result zend_execute_scripts(int type, zval *retval, int file_count, ...) /* {{{ */ 1653 { 1654 va_list files; 1655 int i; 1656 zend_file_handle *file_handle; 1657 zend_op_array *op_array; 1658 zend_result ret = SUCCESS; 1659 1660 va_start(files, file_count); 1661 for (i = 0; i < file_count; i++) { 1662 file_handle = va_arg(files, zend_file_handle *); 1663 if (!file_handle) { 1664 continue; 1665 } 1666 1667 if (ret == FAILURE) { 1668 /* If a failure occurred in one of the earlier files, 1669 * only destroy the following file handles. */ 1670 zend_file_handle_dtor(file_handle); 1671 continue; 1672 } 1673 1674 op_array = zend_compile_file(file_handle, type); 1675 if (file_handle->opened_path) { 1676 zend_hash_add_empty_element(&EG(included_files), file_handle->opened_path); 1677 } 1678 zend_destroy_file_handle(file_handle); 1679 if (op_array) { 1680 zend_execute(op_array, retval); 1681 zend_exception_restore(); 1682 if (UNEXPECTED(EG(exception))) { 1683 if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) { 1684 zend_user_exception_handler(); 1685 } 1686 if (EG(exception)) { 1687 ret = zend_exception_error(EG(exception), E_ERROR); 1688 } 1689 } 1690 destroy_op_array(op_array); 1691 efree_size(op_array, sizeof(zend_op_array)); 1692 } else if (type==ZEND_REQUIRE) { 1693 ret = FAILURE; 1694 } 1695 } 1696 va_end(files); 1697 1698 return ret; 1699 } 1700 /* }}} */ 1701 1702 #define COMPILED_STRING_DESCRIPTION_FORMAT "%s(%d) : %s" 1703 1704 ZEND_API char *zend_make_compiled_string_description(const char *name) /* {{{ */ 1705 { 1706 const char *cur_filename; 1707 int cur_lineno; 1708 char *compiled_string_description; 1709 1710 if (zend_is_compiling()) { 1711 cur_filename = ZSTR_VAL(zend_get_compiled_filename()); 1712 cur_lineno = zend_get_compiled_lineno(); 1713 } else if (zend_is_executing()) { 1714 cur_filename = zend_get_executed_filename(); 1715 cur_lineno = zend_get_executed_lineno(); 1716 } else { 1717 cur_filename = "Unknown"; 1718 cur_lineno = 0; 1719 } 1720 1721 zend_spprintf(&compiled_string_description, 0, COMPILED_STRING_DESCRIPTION_FORMAT, cur_filename, cur_lineno, name); 1722 return compiled_string_description; 1723 } 1724 /* }}} */ 1725 1726 void free_estring(char **str_p) /* {{{ */ 1727 { 1728 efree(*str_p); 1729 } 1730 /* }}} */ 1731 1732 ZEND_API void zend_map_ptr_reset(void) 1733 { 1734 CG(map_ptr_last) = global_map_ptr_last; 1735 } 1736 1737 ZEND_API void *zend_map_ptr_new(void) 1738 { 1739 void **ptr; 1740 1741 if (CG(map_ptr_last) >= CG(map_ptr_size)) { 1742 #if ZEND_MAP_PTR_KIND == ZEND_MAP_PTR_KIND_PTR 1743 // TODO: error ??? 1744 ZEND_UNREACHABLE(); 1745 #elif ZEND_MAP_PTR_KIND == ZEND_MAP_PTR_KIND_PTR_OR_OFFSET 1746 /* Grow map_ptr table */ 1747 CG(map_ptr_size) = ZEND_MM_ALIGNED_SIZE_EX(CG(map_ptr_last) + 1, 4096); 1748 ZEND_MAP_PTR_SET_REAL_BASE(CG(map_ptr_base), perealloc(ZEND_MAP_PTR_REAL_BASE(CG(map_ptr_base)), CG(map_ptr_size) * sizeof(void*), 1)); 1749 #else 1750 # error "Unknown ZEND_MAP_PTR_KIND" 1751 #endif 1752 } 1753 ptr = (void**)ZEND_MAP_PTR_REAL_BASE(CG(map_ptr_base)) + CG(map_ptr_last); 1754 *ptr = NULL; 1755 CG(map_ptr_last)++; 1756 #if ZEND_MAP_PTR_KIND == ZEND_MAP_PTR_KIND_PTR 1757 return ptr; 1758 #elif ZEND_MAP_PTR_KIND == ZEND_MAP_PTR_KIND_PTR_OR_OFFSET 1759 return ZEND_MAP_PTR_PTR2OFFSET(ptr); 1760 #else 1761 # error "Unknown ZEND_MAP_PTR_KIND" 1762 #endif 1763 } 1764 1765 ZEND_API void zend_map_ptr_extend(size_t last) 1766 { 1767 if (last > CG(map_ptr_last)) { 1768 void **ptr; 1769 1770 if (last >= CG(map_ptr_size)) { 1771 #if ZEND_MAP_PTR_KIND == ZEND_MAP_PTR_KIND_PTR 1772 /* This may never happen */ 1773 ZEND_UNREACHABLE(); 1774 #elif ZEND_MAP_PTR_KIND == ZEND_MAP_PTR_KIND_PTR_OR_OFFSET 1775 /* Grow map_ptr table */ 1776 CG(map_ptr_size) = ZEND_MM_ALIGNED_SIZE_EX(last, 4096); 1777 ZEND_MAP_PTR_SET_REAL_BASE(CG(map_ptr_base), perealloc(ZEND_MAP_PTR_REAL_BASE(CG(map_ptr_base)), CG(map_ptr_size) * sizeof(void*), 1)); 1778 #else 1779 # error "Unknown ZEND_MAP_PTR_KIND" 1780 #endif 1781 } 1782 ptr = (void**)ZEND_MAP_PTR_REAL_BASE(CG(map_ptr_base)) + CG(map_ptr_last); 1783 memset(ptr, 0, (last - CG(map_ptr_last)) * sizeof(void*)); 1784 CG(map_ptr_last) = last; 1785 } 1786 } 1787