summaryrefslogtreecommitdiff
path: root/Zend/zend.c
diff options
context:
space:
mode:
Diffstat (limited to 'Zend/zend.c')
-rw-r--r--Zend/zend.c184
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");