diff options
Diffstat (limited to 'Zend/zend.c')
| -rw-r--r-- | Zend/zend.c | 184 |
1 files changed, 127 insertions, 57 deletions
diff --git a/Zend/zend.c b/Zend/zend.c index 72a7b4d588..98d8a803db 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -33,6 +33,7 @@ #include "zend_virtual_cwd.h" #include "zend_smart_str.h" #include "zend_smart_string.h" +#include "zend_cpuinfo.h" #ifdef ZTS ZEND_API int compiler_globals_id; @@ -75,13 +76,18 @@ ZEND_API void (*zend_error_cb)(int type, const char *error_filename, const uint3 void (*zend_printf_to_smart_string)(smart_string *buf, const char *format, va_list ap); void (*zend_printf_to_smart_str)(smart_str *buf, const char *format, va_list ap); ZEND_API char *(*zend_getenv)(char *name, size_t name_len); -ZEND_API zend_string *(*zend_resolve_path)(const char *filename, int filename_len); +ZEND_API zend_string *(*zend_resolve_path)(const char *filename, size_t filename_len); +ZEND_API int (*zend_post_startup_cb)(void) = NULL; void (*zend_on_timeout)(int seconds); static void (*zend_message_dispatcher_p)(zend_long message, const void *data); static zval *(*zend_get_configuration_directive_p)(zend_string *name); +#if ZEND_RC_DEBUG +ZEND_API zend_bool zend_rc_debug = 0; +#endif + static ZEND_INI_MH(OnUpdateErrorReporting) /* {{{ */ { if (!new_value) { @@ -95,16 +101,26 @@ static ZEND_INI_MH(OnUpdateErrorReporting) /* {{{ */ static ZEND_INI_MH(OnUpdateGCEnabled) /* {{{ */ { - OnUpdateBool(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); + zend_bool val; - if (GC_G(gc_enabled)) { - gc_init(); - } + val = zend_ini_parse_bool(new_value); + gc_enable(val); return SUCCESS; } /* }}} */ +static ZEND_INI_DISP(zend_gc_enabled_displayer_cb) /* {{{ */ +{ + if (gc_enabled()) { + ZEND_PUTS("On"); + } else { + ZEND_PUTS("Off"); + } +} +/* }}} */ + + static ZEND_INI_MH(OnUpdateScriptEncoding) /* {{{ */ { if (!CG(multibyte)) { @@ -130,7 +146,7 @@ static ZEND_INI_MH(OnUpdateAssertions) /* {{{ */ p = (zend_long *) (base+(size_t) mh_arg1); - val = zend_atol(ZSTR_VAL(new_value), (int)ZSTR_LEN(new_value)); + val = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value)); if (stage != ZEND_INI_STAGE_STARTUP && stage != ZEND_INI_STAGE_SHUTDOWN && @@ -148,7 +164,7 @@ static ZEND_INI_MH(OnUpdateAssertions) /* {{{ */ ZEND_INI_BEGIN() ZEND_INI_ENTRY("error_reporting", NULL, ZEND_INI_ALL, OnUpdateErrorReporting) STD_ZEND_INI_ENTRY("zend.assertions", "1", ZEND_INI_ALL, OnUpdateAssertions, assertions, zend_executor_globals, executor_globals) - STD_ZEND_INI_BOOLEAN("zend.enable_gc", "1", ZEND_INI_ALL, OnUpdateGCEnabled, gc_enabled, zend_gc_globals, gc_globals) + ZEND_INI_ENTRY3_EX("zend.enable_gc", "1", ZEND_INI_ALL, OnUpdateGCEnabled, NULL, NULL, NULL, zend_gc_enabled_displayer_cb) STD_ZEND_INI_BOOLEAN("zend.multibyte", "0", ZEND_INI_PERDIR, OnUpdateBool, multibyte, zend_compiler_globals, compiler_globals) ZEND_INI_ENTRY("zend.script_encoding", NULL, ZEND_INI_ALL, OnUpdateScriptEncoding) STD_ZEND_INI_BOOLEAN("zend.detect_unicode", "1", ZEND_INI_ALL, OnUpdateBool, detect_unicode, zend_compiler_globals, compiler_globals) @@ -197,6 +213,18 @@ ZEND_API size_t zend_spprintf(char **message, size_t max_len, const char *format } /* }}} */ +ZEND_API size_t zend_spprintf_unchecked(char **message, size_t max_len, const char *format, ...) /* {{{ */ +{ + va_list arg; + size_t len; + + va_start(arg, format); + len = zend_vspprintf(message, max_len, format, arg); + va_end(arg); + return len; +} +/* }}} */ + ZEND_API zend_string *zend_vstrpprintf(size_t max_len, const char *format, va_list ap) /* {{{ */ { smart_str buf = {0}; @@ -228,6 +256,18 @@ ZEND_API zend_string *zend_strpprintf(size_t max_len, const char *format, ...) / } /* }}} */ +ZEND_API zend_string *zend_strpprintf_unchecked(size_t max_len, const char *format, ...) /* {{{ */ +{ + va_list arg; + zend_string *str; + + va_start(arg, format); + str = zend_vstrpprintf(max_len, format, arg); + va_end(arg); + return str; +} +/* }}} */ + static void zend_print_zval_r_to_buf(smart_str *buf, zval *expr, int indent); static void print_hash(smart_str *buf, HashTable *ht, int indent, zend_bool is_object) /* {{{ */ @@ -309,7 +349,7 @@ ZEND_API int zend_make_printable_zval(zval *expr, zval *expr_copy) /* {{{ */ if (Z_TYPE_P(expr) == IS_STRING) { return 0; } else { - ZVAL_STR(expr_copy, _zval_get_string_func(expr)); + ZVAL_STR(expr_copy, zval_get_string_func(expr)); return 1; } } @@ -317,14 +357,15 @@ ZEND_API int zend_make_printable_zval(zval *expr, zval *expr_copy) /* {{{ */ ZEND_API size_t zend_print_zval(zval *expr, int indent) /* {{{ */ { - zend_string *str = zval_get_string(expr); + zend_string *tmp_str; + zend_string *str = zval_get_tmp_string(expr, &tmp_str); size_t len = ZSTR_LEN(str); if (len != 0) { zend_write(ZSTR_VAL(str), len); } - zend_string_release(str); + zend_tmp_string_release(tmp_str); return len; } /* }}} */ @@ -334,16 +375,17 @@ ZEND_API void zend_print_flat_zval_r(zval *expr) /* {{{ */ switch (Z_TYPE_P(expr)) { case IS_ARRAY: ZEND_PUTS("Array ("); - if (ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(expr)) && - ++Z_ARRVAL_P(expr)->u.v.nApplyCount>1) { - ZEND_PUTS(" *RECURSION*"); - Z_ARRVAL_P(expr)->u.v.nApplyCount--; - return; + if (Z_REFCOUNTED_P(expr)) { + if (Z_IS_RECURSIVE_P(expr)) { + ZEND_PUTS(" *RECURSION*"); + return; + } + Z_PROTECT_RECURSION_P(expr); } print_flat_hash(Z_ARRVAL_P(expr)); ZEND_PUTS(")"); - if (ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(expr))) { - Z_ARRVAL_P(expr)->u.v.nApplyCount--; + if (Z_REFCOUNTED_P(expr)) { + Z_UNPROTECT_RECURSION_P(expr); } break; case IS_OBJECT: @@ -353,7 +395,7 @@ ZEND_API void zend_print_flat_zval_r(zval *expr) /* {{{ */ zend_printf("%s Object (", ZSTR_VAL(class_name)); zend_string_release(class_name); - if (Z_OBJ_APPLY_COUNT_P(expr) > 0) { + if (Z_IS_RECURSIVE_P(expr)) { ZEND_PUTS(" *RECURSION*"); return; } @@ -362,9 +404,9 @@ ZEND_API void zend_print_flat_zval_r(zval *expr) /* {{{ */ properties = Z_OBJPROP_P(expr); } if (properties) { - Z_OBJ_INC_APPLY_COUNT_P(expr); + Z_PROTECT_RECURSION_P(expr); print_flat_hash(properties); - Z_OBJ_DEC_APPLY_COUNT_P(expr); + Z_UNPROTECT_RECURSION_P(expr); } ZEND_PUTS(")"); break; @@ -384,15 +426,16 @@ static void zend_print_zval_r_to_buf(smart_str *buf, zval *expr, int indent) /* switch (Z_TYPE_P(expr)) { case IS_ARRAY: smart_str_appends(buf, "Array\n"); - if (ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(expr)) && - ++Z_ARRVAL_P(expr)->u.v.nApplyCount>1) { - smart_str_appends(buf, " *RECURSION*"); - Z_ARRVAL_P(expr)->u.v.nApplyCount--; - return; + if (Z_REFCOUNTED_P(expr)) { + if (Z_IS_RECURSIVE_P(expr)) { + smart_str_appends(buf, " *RECURSION*"); + return; + } + Z_PROTECT_RECURSION_P(expr); } print_hash(buf, Z_ARRVAL_P(expr), indent, 0); - if (ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(expr))) { - Z_ARRVAL_P(expr)->u.v.nApplyCount--; + if (Z_REFCOUNTED_P(expr)) { + Z_UNPROTECT_RECURSION_P(expr); } break; case IS_OBJECT: @@ -405,7 +448,7 @@ static void zend_print_zval_r_to_buf(smart_str *buf, zval *expr, int indent) /* zend_string_release(class_name); smart_str_appends(buf, " Object\n"); - if (Z_OBJ_APPLY_COUNT_P(expr) > 0) { + if (Z_IS_RECURSIVE_P(expr)) { smart_str_appends(buf, " *RECURSION*"); return; } @@ -413,9 +456,9 @@ static void zend_print_zval_r_to_buf(smart_str *buf, zval *expr, int indent) /* break; } - Z_OBJ_INC_APPLY_COUNT_P(expr); + Z_PROTECT_RECURSION_P(expr); print_hash(buf, properties, indent, 1); - Z_OBJ_DEC_APPLY_COUNT_P(expr); + Z_UNPROTECT_RECURSION_P(expr); if (is_temp) { zend_hash_destroy(properties); @@ -429,9 +472,12 @@ static void zend_print_zval_r_to_buf(smart_str *buf, zval *expr, int indent) /* case IS_REFERENCE: zend_print_zval_r_to_buf(buf, Z_REFVAL_P(expr), indent); break; + case IS_STRING: + smart_str_append(buf, Z_STR_P(expr)); + break; default: { - zend_string *str = zval_get_string(expr); + zend_string *str = zval_get_string_func(expr); smart_str_append(buf, str); zend_string_release(str); } @@ -498,19 +544,10 @@ static void zend_init_exception_op(void) /* {{{ */ { memset(EG(exception_op), 0, sizeof(EG(exception_op))); EG(exception_op)[0].opcode = ZEND_HANDLE_EXCEPTION; - EG(exception_op)[0].op1_type = IS_UNUSED; - EG(exception_op)[0].op2_type = IS_UNUSED; - EG(exception_op)[0].result_type = IS_UNUSED; ZEND_VM_SET_OPCODE_HANDLER(EG(exception_op)); EG(exception_op)[1].opcode = ZEND_HANDLE_EXCEPTION; - EG(exception_op)[1].op1_type = IS_UNUSED; - EG(exception_op)[1].op2_type = IS_UNUSED; - EG(exception_op)[1].result_type = IS_UNUSED; ZEND_VM_SET_OPCODE_HANDLER(EG(exception_op)+1); EG(exception_op)[2].opcode = ZEND_HANDLE_EXCEPTION; - EG(exception_op)[2].op1_type = IS_UNUSED; - EG(exception_op)[2].op2_type = IS_UNUSED; - EG(exception_op)[2].result_type = IS_UNUSED; ZEND_VM_SET_OPCODE_HANDLER(EG(exception_op)+2); } /* }}} */ @@ -519,9 +556,6 @@ static void zend_init_call_trampoline_op(void) /* {{{ */ { memset(&EG(call_trampoline_op), 0, sizeof(EG(call_trampoline_op))); EG(call_trampoline_op).opcode = ZEND_CALL_TRAMPOLINE; - EG(call_trampoline_op).op1_type = IS_UNUSED; - EG(call_trampoline_op).op2_type = IS_UNUSED; - EG(call_trampoline_op).result_type = IS_UNUSED; ZEND_VM_SET_OPCODE_HANDLER(&EG(call_trampoline_op)); } /* }}} */ @@ -536,9 +570,34 @@ static void auto_global_dtor(zval *zv) /* {{{ */ static void function_copy_ctor(zval *zv) /* {{{ */ { zend_function *old_func = Z_FUNC_P(zv); - Z_FUNC_P(zv) = pemalloc(sizeof(zend_internal_function), 1); - memcpy(Z_FUNC_P(zv), old_func, sizeof(zend_internal_function)); - function_add_ref(Z_FUNC_P(zv)); + zend_function *func = pemalloc(sizeof(zend_internal_function), 1); + + Z_FUNC_P(zv) = func; + memcpy(func, old_func, sizeof(zend_internal_function)); + function_add_ref(func); + if ((old_func->common.fn_flags & (ZEND_ACC_HAS_RETURN_TYPE|ZEND_ACC_HAS_TYPE_HINTS)) + && old_func->common.arg_info) { + uint32_t i; + uint32_t num_args = old_func->common.num_args + 1; + zend_arg_info *arg_info = old_func->common.arg_info - 1; + zend_arg_info *new_arg_info; + + if (old_func->common.fn_flags & ZEND_ACC_VARIADIC) { + num_args++; + } + new_arg_info = pemalloc(sizeof(zend_arg_info) * num_args, 1); + memcpy(new_arg_info, arg_info, sizeof(zend_arg_info) * num_args); + for (i = 0 ; i < num_args; i++) { + if (ZEND_TYPE_IS_CLASS(arg_info[i].type)) { + zend_string *name = zend_string_dup(ZEND_TYPE_NAME(arg_info[i].type), 1); + + new_arg_info[i].type = + ZEND_TYPE_ENCODE_CLASS( + name, ZEND_TYPE_ALLOW_NULL(arg_info[i].type)); + } + } + func->common.arg_info = new_arg_info + 1; + } } /* }}} */ @@ -681,8 +740,6 @@ static void php_scanner_globals_ctor(zend_php_scanner_globals *scanner_globals_p } /* }}} */ -void zend_init_opcodes_handlers(void); - static void module_destructor_zval(zval *zv) /* {{{ */ { zend_module_entry *module = (zend_module_entry*)Z_PTR_P(zv); @@ -696,8 +753,9 @@ static zend_bool php_auto_globals_create_globals(zend_string *name) /* {{{ */ { zval globals; + /* IS_ARRAY, but with ref-counter 1 and not IS_TYPE_REFCOUNTED */ ZVAL_ARR(&globals, &EG(symbol_table)); - Z_TYPE_INFO_P(&globals) = IS_ARRAY; + Z_TYPE_FLAGS_P(&globals) = 0; ZVAL_NEW_REF(&globals, &globals); zend_hash_update(&EG(symbol_table), name, &globals); return 0; @@ -717,6 +775,8 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions) / extern zend_php_scanner_globals language_scanner_globals; #endif + zend_cpu_startup(); + #ifdef ZEND_WIN32 php_win32_cp_set_by_id(65001); #endif @@ -780,7 +840,7 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions) / /* Set up the default garbage collection implementation. */ gc_collect_cycles = zend_gc_collect_cycles; - zend_init_opcodes_handlers(); + zend_vm_init(); /* set up version */ zend_version_info = strdup(ZEND_CORE_VERSION_INFO); @@ -831,7 +891,7 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions) / zend_interned_strings_init(); zend_startup_builtin_functions(); zend_register_standard_constants(); - zend_register_auto_global(zend_string_init("GLOBALS", sizeof("GLOBALS") - 1, 1), 1, php_auto_globals_create_globals); + zend_register_auto_global(zend_string_init_interned("GLOBALS", sizeof("GLOBALS") - 1, 1), 1, php_auto_globals_create_globals); #ifndef ZTS zend_init_rsrc_plist(); @@ -866,7 +926,7 @@ void zend_register_standard_ini_entries(void) /* {{{ */ /* Unlink the global (r/o) copies of the class, function and constant tables, * and use a fresh r/w copy for the startup thread */ -void zend_post_startup(void) /* {{{ */ +int zend_post_startup(void) /* {{{ */ { #ifdef ZTS zend_encoding **script_encoding_list; @@ -896,11 +956,24 @@ void zend_post_startup(void) /* {{{ */ global_persistent_list = &EG(persistent_list); zend_copy_ini_directives(); #endif + + if (zend_post_startup_cb) { + int (*cb)(void) = zend_post_startup_cb; + + zend_post_startup_cb = NULL; + if (cb() != SUCCESS) { + return FAILURE; + } + } + + return SUCCESS; } /* }}} */ void zend_shutdown(void) /* {{{ */ { + zend_vm_dtor(); + zend_destroy_rsrc_list(&EG(persistent_list)); zend_destroy_modules(); @@ -930,10 +1003,6 @@ void zend_shutdown(void) /* {{{ */ GLOBAL_CONSTANTS_TABLE = NULL; #endif zend_destroy_rsrc_list_dtors(); - -#ifndef ZTS - zend_interned_strings_dtor(); -#endif } /* }}} */ @@ -966,6 +1035,7 @@ ZEND_API ZEND_COLD void _zend_bailout(const char *filename, uint32_t lineno) /* zend_output_debug_string(1, "%s(%d) : Bailed out without a bailout address!", filename, lineno); exit(-1); } + gc_protect(1); CG(unclean_shutdown) = 1; CG(active_class_entry) = NULL; CG(in_compilation) = 0; @@ -1350,7 +1420,7 @@ ZEND_API ZEND_COLD void zend_throw_error(zend_class_entry *exception_ce, const c { va_list va; char *message = NULL; - + if (exception_ce) { if (!instanceof_function(exception_ce, zend_ce_error)) { zend_error(E_NOTICE, "Error exceptions must be derived from Error"); |
