summaryrefslogtreecommitdiff
path: root/Zend/zend.c
diff options
context:
space:
mode:
Diffstat (limited to 'Zend/zend.c')
-rw-r--r--Zend/zend.c481
1 files changed, 320 insertions, 161 deletions
diff --git a/Zend/zend.c b/Zend/zend.c
index 18ec232262..dc1445bf32 100644
--- a/Zend/zend.c
+++ b/Zend/zend.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| Zend Engine |
+----------------------------------------------------------------------+
- | Copyright (c) 1998-2018 Zend Technologies Ltd. (http://www.zend.com) |
+ | Copyright (c) Zend Technologies Ltd. (http://www.zend.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 2.00 of the Zend license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -33,9 +33,13 @@
#include "zend_smart_string.h"
#include "zend_cpuinfo.h"
+static size_t global_map_ptr_last = 0;
+
#ifdef ZTS
ZEND_API int compiler_globals_id;
ZEND_API int executor_globals_id;
+ZEND_API size_t compiler_globals_offset;
+ZEND_API size_t executor_globals_offset;
static HashTable *global_function_table = NULL;
static HashTable *global_class_table = NULL;
static HashTable *global_constants_table = NULL;
@@ -59,7 +63,7 @@ ZEND_API zend_bool zend_dtrace_enabled;
/* version information */
static char *zend_version_info;
static uint32_t zend_version_info_length;
-#define ZEND_CORE_VERSION_INFO "Zend Engine v" ZEND_VERSION ", Copyright (c) 1998-2018 Zend Technologies\n"
+#define ZEND_CORE_VERSION_INFO "Zend Engine v" ZEND_VERSION ", Copyright (c) Zend Technologies\n"
#define PRINT_ZVAL_INDENT 4
/* true multithread-shared globals */
@@ -76,6 +80,8 @@ 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, size_t filename_len);
ZEND_API int (*zend_post_startup_cb)(void) = NULL;
+ZEND_API void (*zend_post_shutdown_cb)(void) = NULL;
+ZEND_API int (*zend_preload_autoload)(zend_string *filename) = NULL;
void (*zend_on_timeout)(int seconds);
@@ -159,6 +165,12 @@ static ZEND_INI_MH(OnUpdateAssertions) /* {{{ */
}
/* }}} */
+#if ZEND_DEBUG
+# define SIGNAL_CHECK_DEFAULT "1"
+#else
+# define SIGNAL_CHECK_DEFAULT "0"
+#endif
+
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)
@@ -167,8 +179,9 @@ ZEND_INI_BEGIN()
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)
#ifdef ZEND_SIGNALS
- STD_ZEND_INI_BOOLEAN("zend.signal_check", "0", ZEND_INI_SYSTEM, OnUpdateBool, check, zend_signal_globals_t, zend_signal_globals)
+ STD_ZEND_INI_BOOLEAN("zend.signal_check", SIGNAL_CHECK_DEFAULT, ZEND_INI_SYSTEM, OnUpdateBool, check, zend_signal_globals_t, zend_signal_globals)
#endif
+ STD_ZEND_INI_BOOLEAN("zend.exception_ignore_args", "0", ZEND_INI_ALL, OnUpdateBool, exception_ignore_args, zend_executor_globals, executor_globals)
ZEND_INI_END()
ZEND_API size_t zend_vspprintf(char **pbuf, size_t max_len, const char *format, va_list ap) /* {{{ */
@@ -388,19 +401,17 @@ ZEND_API void zend_print_flat_zval_r(zval *expr) /* {{{ */
break;
case IS_OBJECT:
{
- HashTable *properties = NULL;
+ HashTable *properties;
zend_string *class_name = Z_OBJ_HANDLER_P(expr, get_class_name)(Z_OBJ_P(expr));
zend_printf("%s Object (", ZSTR_VAL(class_name));
zend_string_release_ex(class_name, 0);
- if (GC_IS_RECURSIVE(Z_OBJ_P(expr))) {
+ if (GC_IS_RECURSIVE(Z_COUNTED_P(expr))) {
ZEND_PUTS(" *RECURSION*");
return;
}
- if (Z_OBJ_HANDLER_P(expr, get_properties)) {
- properties = Z_OBJPROP_P(expr);
- }
+ properties = Z_OBJPROP_P(expr);
if (properties) {
GC_PROTECT_RECURSION(Z_OBJ_P(expr));
print_flat_hash(properties);
@@ -439,7 +450,6 @@ static void zend_print_zval_r_to_buf(smart_str *buf, zval *expr, int indent) /*
case IS_OBJECT:
{
HashTable *properties;
- int is_temp;
zend_string *class_name = Z_OBJ_HANDLER_P(expr, get_class_name)(Z_OBJ_P(expr));
smart_str_appends(buf, ZSTR_VAL(class_name));
@@ -450,7 +460,8 @@ static void zend_print_zval_r_to_buf(smart_str *buf, zval *expr, int indent) /*
smart_str_appends(buf, " *RECURSION*");
return;
}
- if ((properties = Z_OBJDEBUG_P(expr, is_temp)) == NULL) {
+
+ if ((properties = zend_get_properties_for(expr, ZEND_PROP_PURPOSE_DEBUG)) == NULL) {
break;
}
@@ -458,10 +469,7 @@ static void zend_print_zval_r_to_buf(smart_str *buf, zval *expr, int indent) /*
print_hash(buf, properties, indent, 1);
GC_UNPROTECT_RECURSION(Z_OBJ_P(expr));
- if (is_temp) {
- zend_hash_destroy(properties);
- FREE_HASHTABLE(properties);
- }
+ zend_release_properties(properties);
break;
}
case IS_LONG:
@@ -523,6 +531,8 @@ static void zend_set_default_compile_time_values(void) /* {{{ */
/* default compile-time values */
CG(short_tags) = short_tags_default;
CG(compiler_options) = compiler_options_default;
+
+ CG(rtd_key_counter) = 0;
}
/* }}} */
@@ -568,8 +578,13 @@ static void auto_global_dtor(zval *zv) /* {{{ */
static void function_copy_ctor(zval *zv) /* {{{ */
{
zend_function *old_func = Z_FUNC_P(zv);
- zend_function *func = pemalloc(sizeof(zend_internal_function), 1);
+ zend_function *func;
+ if (old_func->type == ZEND_USER_FUNCTION) {
+ ZEND_ASSERT(old_func->op_array.fn_flags & ZEND_ACC_IMMUTABLE);
+ return;
+ }
+ func = pemalloc(sizeof(zend_internal_function), 1);
Z_FUNC_P(zv) = func;
memcpy(func, old_func, sizeof(zend_internal_function));
function_add_ref(func);
@@ -630,13 +645,22 @@ static void compiler_globals_ctor(zend_compiler_globals *compiler_globals) /* {{
zend_hash_init_ex(compiler_globals->auto_globals, 8, NULL, auto_global_dtor, 1, 0);
zend_hash_copy(compiler_globals->auto_globals, global_auto_globals_table, auto_global_copy_ctor);
- compiler_globals->last_static_member = zend_hash_num_elements(compiler_globals->class_table);
- if (compiler_globals->last_static_member) {
- compiler_globals->static_members_table = calloc(compiler_globals->last_static_member, sizeof(zval*));
- } else {
- compiler_globals->static_members_table = NULL;
- }
compiler_globals->script_encoding_list = NULL;
+
+#if ZEND_MAP_PTR_KIND == ZEND_MAP_PTR_KIND_PTR_OR_OFFSET
+ /* Map region is going to be created and resized at run-time. */
+ compiler_globals->map_ptr_base = NULL;
+ compiler_globals->map_ptr_size = 0;
+ compiler_globals->map_ptr_last = global_map_ptr_last;
+ if (compiler_globals->map_ptr_last) {
+ /* Allocate map_ptr table */
+ compiler_globals->map_ptr_size = ZEND_MM_ALIGNED_SIZE_EX(compiler_globals->map_ptr_last, 4096);
+ compiler_globals->map_ptr_base = pemalloc(compiler_globals->map_ptr_size * sizeof(void*), 1);
+ memset(compiler_globals->map_ptr_base, 0, compiler_globals->map_ptr_last * sizeof(void*));
+ }
+#else
+# error "Unknown ZEND_MAP_PTR_KIND"
+#endif
}
/* }}} */
@@ -654,20 +678,19 @@ static void compiler_globals_dtor(zend_compiler_globals *compiler_globals) /* {{
zend_hash_destroy(compiler_globals->auto_globals);
free(compiler_globals->auto_globals);
}
- if (compiler_globals->static_members_table) {
- free(compiler_globals->static_members_table);
- }
if (compiler_globals->script_encoding_list) {
pefree((char*)compiler_globals->script_encoding_list, 1);
}
- compiler_globals->last_static_member = 0;
+ if (compiler_globals->map_ptr_base) {
+ free(compiler_globals->map_ptr_base);
+ compiler_globals->map_ptr_base = NULL;
+ compiler_globals->map_ptr_size = 0;
+ }
}
/* }}} */
static void executor_globals_ctor(zend_executor_globals *executor_globals) /* {{{ */
{
- ZEND_TSRMLS_CACHE_UPDATE();
-
zend_startup_constants();
zend_copy_constants(executor_globals->zend_constants, GLOBAL_CONSTANTS_TABLE);
zend_init_rsrc_plist();
@@ -760,14 +783,13 @@ static zend_bool php_auto_globals_create_globals(zend_string *name) /* {{{ */
}
/* }}} */
-int zend_startup(zend_utility_functions *utility_functions, char **extensions) /* {{{ */
+int zend_startup(zend_utility_functions *utility_functions) /* {{{ */
{
#ifdef ZTS
zend_compiler_globals *compiler_globals;
zend_executor_globals *executor_globals;
extern ZEND_API ts_rsrc_id ini_scanner_globals_id;
extern ZEND_API ts_rsrc_id language_scanner_globals_id;
- ZEND_TSRMLS_CACHE_UPDATE();
#else
extern zend_ini_scanner_globals ini_scanner_globals;
extern zend_php_scanner_globals language_scanner_globals;
@@ -858,10 +880,10 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions) /
zend_init_rsrc_list_dtors();
#ifdef ZTS
- ts_allocate_id(&compiler_globals_id, sizeof(zend_compiler_globals), (ts_allocate_ctor) compiler_globals_ctor, (ts_allocate_dtor) compiler_globals_dtor);
- ts_allocate_id(&executor_globals_id, sizeof(zend_executor_globals), (ts_allocate_ctor) executor_globals_ctor, (ts_allocate_dtor) executor_globals_dtor);
- ts_allocate_id(&language_scanner_globals_id, sizeof(zend_php_scanner_globals), (ts_allocate_ctor) php_scanner_globals_ctor, NULL);
- ts_allocate_id(&ini_scanner_globals_id, sizeof(zend_ini_scanner_globals), (ts_allocate_ctor) ini_scanner_globals_ctor, NULL);
+ 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);
+ 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);
+ 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);
+ 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);
compiler_globals = ts_resource(compiler_globals_id);
executor_globals = ts_resource(executor_globals_id);
@@ -883,6 +905,22 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions) /
#ifdef ZEND_WIN32
zend_get_windows_version_info(&EG(windows_version_info));
#endif
+# if ZEND_MAP_PTR_KIND == ZEND_MAP_PTR_KIND_PTR
+ /* Create a map region, used for indirect pointers from shared to
+ * process memory. It's allocatred once and never resized.
+ * All processes must map it into the same address space.
+ */
+ CG(map_ptr_size) = 1024 * 1024; // TODO: initial size ???
+ CG(map_ptr_last) = 0;
+ CG(map_ptr_base) = pemalloc(CG(map_ptr_size) * sizeof(void*), 1);
+# elif ZEND_MAP_PTR_KIND == ZEND_MAP_PTR_KIND_PTR_OR_OFFSET
+ /* Map region is going to be created and resized at run-time. */
+ CG(map_ptr_base) = NULL;
+ CG(map_ptr_size) = 0;
+ CG(map_ptr_last) = 0;
+# else
+# error "Unknown ZEND_MAP_PTR_KIND"
+# endif
#endif
EG(error_reporting) = E_ALL & ~E_NOTICE;
@@ -921,6 +959,35 @@ void zend_register_standard_ini_entries(void) /* {{{ */
}
/* }}} */
+static void zend_resolve_property_types(void) /* {{{ */
+{
+ zend_class_entry *ce;
+ zend_property_info *prop_info;
+
+ ZEND_HASH_FOREACH_PTR(CG(class_table), ce) {
+ if (ce->type != ZEND_INTERNAL_CLASS) {
+ continue;
+ }
+
+ if (UNEXPECTED(ZEND_CLASS_HAS_TYPE_HINTS(ce))) {
+ ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop_info) {
+ if (ZEND_TYPE_IS_NAME(prop_info->type)) {
+ zend_string *type_name = ZEND_TYPE_NAME(prop_info->type);
+ zend_string *lc_type_name = zend_string_tolower(type_name);
+ zend_class_entry *prop_ce = zend_hash_find_ptr(CG(class_table), lc_type_name);
+
+ ZEND_ASSERT(prop_ce && prop_ce->type == ZEND_INTERNAL_CLASS);
+ prop_info->type = ZEND_TYPE_ENCODE_CE(prop_ce, ZEND_TYPE_ALLOW_NULL(prop_info->type));
+ zend_string_release(lc_type_name);
+ zend_string_release(type_name);
+ }
+ } ZEND_HASH_FOREACH_END();
+ }
+ ce->ce_flags |= ZEND_ACC_PROPERTY_TYPES_RESOLVED;
+ } ZEND_HASH_FOREACH_END();
+}
+/* }}} */
+
/* Unlink the global (r/o) copies of the class, function and constant tables,
* and use a fresh r/w copy for the startup thread
*/
@@ -931,17 +998,35 @@ int zend_post_startup(void) /* {{{ */
zend_compiler_globals *compiler_globals = ts_resource(compiler_globals_id);
zend_executor_globals *executor_globals = ts_resource(executor_globals_id);
+#endif
+
+ zend_resolve_property_types();
+
+ if (zend_post_startup_cb) {
+ int (*cb)(void) = zend_post_startup_cb;
+
+ zend_post_startup_cb = NULL;
+ if (cb() != SUCCESS) {
+ return FAILURE;
+ }
+ }
+#ifdef ZTS
*GLOBAL_FUNCTION_TABLE = *compiler_globals->function_table;
*GLOBAL_CLASS_TABLE = *compiler_globals->class_table;
*GLOBAL_CONSTANTS_TABLE = *executor_globals->zend_constants;
+ global_map_ptr_last = compiler_globals->map_ptr_last;
short_tags_default = CG(short_tags);
compiler_options_default = CG(compiler_options);
zend_destroy_rsrc_list(&EG(persistent_list));
free(compiler_globals->function_table);
+ compiler_globals->function_table = NULL;
free(compiler_globals->class_table);
+ compiler_globals->class_table = NULL;
+ free(compiler_globals->map_ptr_base);
+ compiler_globals->map_ptr_base = NULL;
if ((script_encoding_list = (zend_encoding **)compiler_globals->script_encoding_list)) {
compiler_globals_ctor(compiler_globals);
compiler_globals->script_encoding_list = (const zend_encoding **)script_encoding_list;
@@ -949,21 +1034,15 @@ int zend_post_startup(void) /* {{{ */
compiler_globals_ctor(compiler_globals);
}
free(EG(zend_constants));
+ EG(zend_constants) = NULL;
executor_globals_ctor(executor_globals);
global_persistent_list = &EG(persistent_list);
zend_copy_ini_directives();
+#else
+ global_map_ptr_last = CG(map_ptr_last);
#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;
}
/* }}} */
@@ -999,6 +1078,19 @@ void zend_shutdown(void) /* {{{ */
GLOBAL_CLASS_TABLE = NULL;
GLOBAL_AUTO_GLOBALS_TABLE = NULL;
GLOBAL_CONSTANTS_TABLE = NULL;
+ ts_free_id(executor_globals_id);
+ ts_free_id(compiler_globals_id);
+#else
+ if (CG(map_ptr_base)) {
+ free(CG(map_ptr_base));
+ CG(map_ptr_base) = NULL;
+ CG(map_ptr_size) = 0;
+ }
+ if (CG(script_encoding_list)) {
+ free(CG(script_encoding_list));
+ CG(script_encoding_list) = NULL;
+ CG(script_encoding_list_size) = 0;
+ }
#endif
zend_destroy_rsrc_list_dtors();
}
@@ -1007,7 +1099,6 @@ void zend_shutdown(void) /* {{{ */
void zend_set_utility_values(zend_utility_values *utility_values) /* {{{ */
{
zend_uv = *utility_values;
- zend_uv.import_use_extension_length = (uint32_t)strlen(zend_uv.import_use_extension);
}
/* }}} */
@@ -1026,7 +1117,7 @@ ZEND_COLD void zenderror(const char *error) /* {{{ */
/* }}} */
BEGIN_EXTERN_C()
-ZEND_API ZEND_COLD void _zend_bailout(const char *filename, uint32_t lineno) /* {{{ */
+ZEND_API ZEND_COLD ZEND_NORETURN void _zend_bailout(const char *filename, uint32_t lineno) /* {{{ */
{
if (!EG(bailout)) {
@@ -1080,6 +1171,9 @@ ZEND_API void zend_activate(void) /* {{{ */
init_compiler();
init_executor();
startup_scanner();
+ if (CG(map_ptr_last)) {
+ memset(CG(map_ptr_base), 0, CG(map_ptr_last) * sizeof(void*));
+ }
}
/* }}} */
@@ -1165,20 +1259,13 @@ ZEND_API zval *zend_get_configuration_directive(zend_string *name) /* {{{ */
} \
} while (0)
-#if !defined(HAVE_NORETURN) || defined(HAVE_NORETURN_ALIAS)
-ZEND_API ZEND_COLD void zend_error(int type, const char *format, ...) /* {{{ */
-#else
-static ZEND_COLD void zend_error_va_list(int type, const char *format, va_list args)
-#endif
+static ZEND_COLD void zend_error_va_list(
+ int type, const char *error_filename, uint32_t error_lineno,
+ const char *format, va_list args)
{
-#if !defined(HAVE_NORETURN) || defined(HAVE_NORETURN_ALIAS)
- va_list args;
-#endif
va_list usr_copy;
zval params[5];
zval retval;
- const char *error_filename;
- uint32_t error_lineno = 0;
zval orig_user_error_handler;
zend_bool in_compilation;
zend_class_entry *saved_class_entry;
@@ -1219,70 +1306,15 @@ static ZEND_COLD void zend_error_va_list(int type, const char *format, va_list a
}
}
- /* Obtain relevant filename and lineno */
- switch (type) {
- case E_CORE_ERROR:
- case E_CORE_WARNING:
- error_filename = NULL;
- error_lineno = 0;
- break;
- case E_PARSE:
- case E_COMPILE_ERROR:
- case E_COMPILE_WARNING:
- case E_ERROR:
- case E_NOTICE:
- case E_STRICT:
- case E_DEPRECATED:
- case E_WARNING:
- case E_USER_ERROR:
- case E_USER_WARNING:
- case E_USER_NOTICE:
- case E_USER_DEPRECATED:
- case E_RECOVERABLE_ERROR:
- if (zend_is_compiling()) {
- error_filename = ZSTR_VAL(zend_get_compiled_filename());
- error_lineno = zend_get_compiled_lineno();
- } else if (zend_is_executing()) {
- error_filename = zend_get_executed_filename();
- if (error_filename[0] == '[') { /* [no active file] */
- error_filename = NULL;
- error_lineno = 0;
- } else {
- error_lineno = zend_get_executed_lineno();
- }
- } else {
- error_filename = NULL;
- error_lineno = 0;
- }
- break;
- default:
- error_filename = NULL;
- error_lineno = 0;
- break;
- }
- if (!error_filename) {
- error_filename = "Unknown";
- }
-
#ifdef HAVE_DTRACE
if (DTRACE_ERROR_ENABLED()) {
char *dtrace_error_buffer;
-#if !defined(HAVE_NORETURN) || defined(HAVE_NORETURN_ALIAS)
- va_start(args, format);
-#endif
zend_vspprintf(&dtrace_error_buffer, 0, format, args);
DTRACE_ERROR(dtrace_error_buffer, (char *)error_filename, error_lineno);
efree(dtrace_error_buffer);
-#if !defined(HAVE_NORETURN) || defined(HAVE_NORETURN_ALIAS)
- va_end(args);
-#endif
}
#endif /* HAVE_DTRACE */
-#if !defined(HAVE_NORETURN) || defined(HAVE_NORETURN_ALIAS)
- va_start(args, format);
-#endif
-
/* if we don't have a user defined error handler */
if (Z_TYPE(EG(user_error_handler)) == IS_UNDEF
|| !(EG(user_error_handler_error_reporting) & type)
@@ -1328,7 +1360,7 @@ static ZEND_COLD void zend_error_va_list(int type, const char *format, va_list a
/* User error handler may include() additinal PHP files.
* If an error was generated during comilation PHP will compile
- * such scripts recursivly, but some CG() variables may be
+ * such scripts recursively, but some CG() variables may be
* inconsistent. */
in_compilation = CG(in_compilation);
@@ -1376,10 +1408,6 @@ static ZEND_COLD void zend_error_va_list(int type, const char *format, va_list a
break;
}
-#if !defined(HAVE_NORETURN) || defined(HAVE_NORETURN_ALIAS)
- va_end(args);
-#endif
-
if (type == E_PARSE) {
/* eval() errors do not affect exit_status */
if (!(EG(current_execute_data) &&
@@ -1393,30 +1421,110 @@ static ZEND_COLD void zend_error_va_list(int type, const char *format, va_list a
}
/* }}} */
-#ifdef HAVE_NORETURN
-# ifdef HAVE_NORETURN_ALIAS
-ZEND_COLD void zend_error_noreturn(int type, const char *format, ...) __attribute__ ((alias("zend_error"),noreturn));
-# else
-ZEND_API ZEND_COLD void zend_error(int type, const char *format, ...) /* {{{ */
+static ZEND_COLD void get_filename_lineno(int type, const char **filename, uint32_t *lineno) {
+ /* Obtain relevant filename and lineno */
+ switch (type) {
+ case E_CORE_ERROR:
+ case E_CORE_WARNING:
+ *filename = NULL;
+ *lineno = 0;
+ break;
+ case E_PARSE:
+ case E_COMPILE_ERROR:
+ case E_COMPILE_WARNING:
+ case E_ERROR:
+ case E_NOTICE:
+ case E_STRICT:
+ case E_DEPRECATED:
+ case E_WARNING:
+ case E_USER_ERROR:
+ case E_USER_WARNING:
+ case E_USER_NOTICE:
+ case E_USER_DEPRECATED:
+ case E_RECOVERABLE_ERROR:
+ if (zend_is_compiling()) {
+ *filename = ZSTR_VAL(zend_get_compiled_filename());
+ *lineno = zend_get_compiled_lineno();
+ } else if (zend_is_executing()) {
+ *filename = zend_get_executed_filename();
+ if ((*filename)[0] == '[') { /* [no active file] */
+ *filename = NULL;
+ *lineno = 0;
+ } else {
+ *lineno = zend_get_executed_lineno();
+ }
+ } else {
+ *filename = NULL;
+ *lineno = 0;
+ }
+ break;
+ default:
+ *filename = NULL;
+ *lineno = 0;
+ break;
+ }
+ if (!*filename) {
+ *filename = "Unknown";
+ }
+}
+
+ZEND_API ZEND_COLD void zend_error_at(
+ int type, const char *filename, uint32_t lineno, const char *format, ...) {
+ va_list args;
+
+ if (!filename) {
+ uint32_t dummy_lineno;
+ get_filename_lineno(type, &filename, &dummy_lineno);
+ }
+
+ va_start(args, format);
+ zend_error_va_list(type, filename, lineno, format, args);
+ va_end(args);
+}
+
+ZEND_API ZEND_COLD void zend_error(int type, const char *format, ...) {
+ const char *filename;
+ uint32_t lineno;
+ va_list args;
+
+ get_filename_lineno(type, &filename, &lineno);
+ va_start(args, format);
+ zend_error_va_list(type, filename, lineno, format, args);
+ va_end(args);
+}
+
+ZEND_API ZEND_COLD ZEND_NORETURN void zend_error_at_noreturn(
+ int type, const char *filename, uint32_t lineno, const char *format, ...)
{
- va_list va;
+ va_list args;
- va_start(va, format);
- zend_error_va_list(type, format, va);
- va_end(va);
+ if (!filename) {
+ uint32_t dummy_lineno;
+ get_filename_lineno(type, &filename, &dummy_lineno);
+ }
+
+ va_start(args, format);
+ zend_error_va_list(type, filename, lineno, format, args);
+ va_end(args);
+ /* Should never reach this. */
+ abort();
}
+/* }}} */
ZEND_API ZEND_COLD ZEND_NORETURN void zend_error_noreturn(int type, const char *format, ...)
{
- va_list va;
+ const char *filename;
+ uint32_t lineno;
+ va_list args;
- va_start(va, format);
- zend_error_va_list(type, format, va);
- va_end(va);
+ get_filename_lineno(type, &filename, &lineno);
+ va_start(args, format);
+ zend_error_va_list(type, filename, lineno, format, args);
+ va_end(args);
+ /* Should never reach this. */
+ abort();
}
/* }}} */
-# endif
-#endif
ZEND_API ZEND_COLD void zend_throw_error(zend_class_entry *exception_ce, const char *format, ...) /* {{{ */
{
@@ -1432,6 +1540,11 @@ ZEND_API ZEND_COLD void zend_throw_error(zend_class_entry *exception_ce, const c
exception_ce = zend_ce_error;
}
+ /* Marker used to disable exception generation during preloading. */
+ if (EG(exception) == (void*)(uintptr_t)-1) {
+ return;
+ }
+
va_start(va, format);
zend_vspprintf(&message, 0, format, va);
@@ -1519,29 +1632,25 @@ ZEND_API ZEND_COLD void zend_output_debug_string(zend_bool trigger_break, const
}
/* }}} */
-ZEND_API void zend_try_exception_handler() /* {{{ */
+ZEND_API ZEND_COLD void zend_user_exception_handler(void) /* {{{ */
{
- if (EG(exception)) {
- if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) {
- zval orig_user_exception_handler;
- zval params[1], retval2;
- zend_object *old_exception;
- old_exception = EG(exception);
+ zval orig_user_exception_handler;
+ zval params[1], retval2;
+ zend_object *old_exception;
+ old_exception = EG(exception);
+ EG(exception) = NULL;
+ ZVAL_OBJ(&params[0], old_exception);
+ ZVAL_COPY_VALUE(&orig_user_exception_handler, &EG(user_exception_handler));
+
+ if (call_user_function(CG(function_table), NULL, &orig_user_exception_handler, &retval2, 1, params) == SUCCESS) {
+ zval_ptr_dtor(&retval2);
+ if (EG(exception)) {
+ OBJ_RELEASE(EG(exception));
EG(exception) = NULL;
- ZVAL_OBJ(&params[0], old_exception);
- ZVAL_COPY_VALUE(&orig_user_exception_handler, &EG(user_exception_handler));
-
- if (call_user_function(CG(function_table), NULL, &orig_user_exception_handler, &retval2, 1, params) == SUCCESS) {
- zval_ptr_dtor(&retval2);
- if (EG(exception)) {
- OBJ_RELEASE(EG(exception));
- EG(exception) = NULL;
- }
- OBJ_RELEASE(old_exception);
- } else {
- EG(exception) = old_exception;
- }
}
+ OBJ_RELEASE(old_exception);
+ } else {
+ EG(exception) = old_exception;
}
} /* }}} */
@@ -1567,9 +1676,13 @@ ZEND_API int zend_execute_scripts(int type, zval *retval, int file_count, ...) /
if (op_array) {
zend_execute(op_array, retval);
zend_exception_restore();
- zend_try_exception_handler();
- if (EG(exception)) {
- zend_exception_error(EG(exception), E_ERROR);
+ if (UNEXPECTED(EG(exception))) {
+ if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) {
+ zend_user_exception_handler();
+ }
+ if (EG(exception)) {
+ zend_exception_error(EG(exception), E_ERROR);
+ }
}
destroy_op_array(op_array);
efree_size(op_array, sizeof(zend_op_array));
@@ -1614,12 +1727,58 @@ void free_estring(char **str_p) /* {{{ */
}
/* }}} */
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * indent-tabs-mode: t
- * End:
- * vim600: sw=4 ts=4 fdm=marker
- * vim<600: sw=4 ts=4
- */
+ZEND_API void zend_map_ptr_reset(void)
+{
+ CG(map_ptr_last) = global_map_ptr_last;
+}
+
+ZEND_API void *zend_map_ptr_new(void)
+{
+ void **ptr;
+
+ if (CG(map_ptr_last) >= CG(map_ptr_size)) {
+#if ZEND_MAP_PTR_KIND == ZEND_MAP_PTR_KIND_PTR
+ // TODO: error ???
+ ZEND_ASSERT(0);
+#elif ZEND_MAP_PTR_KIND == ZEND_MAP_PTR_KIND_PTR_OR_OFFSET
+ /* Grow map_ptr table */
+ CG(map_ptr_size) = ZEND_MM_ALIGNED_SIZE_EX(CG(map_ptr_last) + 1, 4096);
+ CG(map_ptr_base) = perealloc(CG(map_ptr_base), CG(map_ptr_size) * sizeof(void*), 1);
+#else
+# error "Unknown ZEND_MAP_PTR_KIND"
+#endif
+ }
+ ptr = (void**)CG(map_ptr_base) + CG(map_ptr_last);
+ *ptr = NULL;
+ CG(map_ptr_last)++;
+#if ZEND_MAP_PTR_KIND == ZEND_MAP_PTR_KIND_PTR
+ return ptr;
+#elif ZEND_MAP_PTR_KIND == ZEND_MAP_PTR_KIND_PTR_OR_OFFSET
+ return ZEND_MAP_PTR_PTR2OFFSET(ptr);
+#else
+# error "Unknown ZEND_MAP_PTR_KIND"
+#endif
+}
+
+ZEND_API void zend_map_ptr_extend(size_t last)
+{
+ if (last > CG(map_ptr_last)) {
+ void **ptr;
+
+ if (last >= CG(map_ptr_size)) {
+#if ZEND_MAP_PTR_KIND == ZEND_MAP_PTR_KIND_PTR
+ /* This may never happen */
+ ZEND_ASSERT(0);
+#elif ZEND_MAP_PTR_KIND == ZEND_MAP_PTR_KIND_PTR_OR_OFFSET
+ /* Grow map_ptr table */
+ CG(map_ptr_size) = ZEND_MM_ALIGNED_SIZE_EX(last, 4096);
+ CG(map_ptr_base) = perealloc(CG(map_ptr_base), CG(map_ptr_size) * sizeof(void*), 1);
+#else
+# error "Unknown ZEND_MAP_PTR_KIND"
+#endif
+ }
+ ptr = (void**)CG(map_ptr_base) + CG(map_ptr_last);
+ memset(ptr, 0, (last - CG(map_ptr_last)) * sizeof(void*));
+ CG(map_ptr_last) = last;
+ }
+}