diff --git a/Zend/tests/error_handler_001.phpt b/Zend/tests/error_handler_001.phpt new file mode 100644 index 0000000000000..9e6a2df1105ef --- /dev/null +++ b/Zend/tests/error_handler_001.phpt @@ -0,0 +1,30 @@ +--TEST-- +Allow error handler declare referenced parameters +--FILE-- + +--EXPECTF-- +Warning: [Prefix] - Undefined variable: undefined - [Suffix] in a-new-file.ext.php on line 999 +array(4) { + ["type"]=> + int(2) + ["message"]=> + string(51) "[Prefix] - Undefined variable: undefined - [Suffix]" + ["file"]=> + string(%d) "a-new-file.ext.php" + ["line"]=> + int(999) +} diff --git a/Zend/tests/error_handler_002.phpt b/Zend/tests/error_handler_002.phpt new file mode 100644 index 0000000000000..3b4ce756b0355 --- /dev/null +++ b/Zend/tests/error_handler_002.phpt @@ -0,0 +1,25 @@ +--TEST-- +Allow error handler declare referenced parameters: with exception +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught exception 'Exception' with message 'exception from handler' in %s:%d +Stack trace: +#0 %s(%d): {closure}(2, '[Prefix] - Unde...', 'a-new-file.ext....', 999, Array) +#1 {main} + thrown in %s on line %d diff --git a/Zend/tests/error_handler_003.phpt b/Zend/tests/error_handler_003.phpt new file mode 100644 index 0000000000000..278fdb5ea7cb2 --- /dev/null +++ b/Zend/tests/error_handler_003.phpt @@ -0,0 +1,34 @@ +--TEST-- +Allow error handler declare referenced parameters: wrong type +--FILE-- + +--EXPECTF-- +Notice: Array to string conversion in %s on line %d + +Notice: Array to string conversion in %s on line %d + +Unknown error: Array in Array on line 0 +array(4) { + ["type"]=> + int(999) + ["message"]=> + string(5) "Array" + ["file"]=> + string(5) "Array" + ["line"]=> + int(0) +} diff --git a/Zend/zend.c b/Zend/zend.c index dcc95a851a688..6bec27e0f9e7a 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -954,6 +954,15 @@ ZEND_API zval *zend_get_configuration_directive(zend_string *name) /* {{{ */ } \ } while (0) +static inline void _zend_error_cb_proxy(int type, const char *error_filename, const uint error_lineno, const char *format, ...) /* {{{ */ +{ + va_list ap; + va_start(ap, format); + zend_error_cb(type, error_filename, error_lineno, format, ap); + va_end(ap); +} +/* }}} */ + #if !defined(ZEND_WIN32) && !defined(DARWIN) ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */ #else @@ -1116,6 +1125,9 @@ static void zend_error_va_list(int type, const char *format, va_list args) ZVAL_LONG(¶ms[3], error_lineno); + ZVAL_MAKE_REF(¶ms[0]); + ZVAL_MAKE_REF(¶ms[3]); + symbol_table = zend_rebuild_symbol_table(); /* during shutdown the symbol table table can be still null */ @@ -1145,16 +1157,48 @@ static void zend_error_va_list(int type, const char *format, va_list args) } ZVAL_UNDEF(&retval); - if (call_user_function_ex(CG(function_table), NULL, &orig_user_error_handler, &retval, 5, params, 1, NULL) == SUCCESS) { - if (Z_TYPE(retval) != IS_UNDEF) { - if (Z_TYPE(retval) == IS_FALSE) { - zend_error_cb(type, error_filename, error_lineno, format, args); + + { + int result = call_user_function_ex(CG(function_table), NULL, &orig_user_error_handler, &retval, 5, params, 1, NULL); + zval *z_errtype = Z_REFVAL(params[0]); + zval *z_errmsg = ¶ms[1]; + zval *z_errfile = ¶ms[2]; + zval *z_errline = Z_REFVAL(params[3]); + + int errtype = type; + char *errfile = (char *)error_filename; + int errline = error_lineno; + char *errmsg = Z_STR_P(z_errmsg)->val; + + convert_to_long(z_errtype); + errtype = Z_LVAL_P(z_errtype); + + if (Z_ISREF_P(z_errmsg)) { + z_errmsg = Z_REFVAL_P(z_errmsg); + convert_to_string(z_errmsg); + errmsg = Z_STR_P(z_errmsg)->val; + } + + if (Z_ISREF_P(z_errfile)) { + z_errfile = Z_REFVAL_P(z_errfile); + convert_to_string(z_errfile); + errfile = Z_STR_P(z_errfile)->val; + } + + convert_to_long(z_errline); + errline = Z_LVAL_P(z_errline); + + if (result == SUCCESS) { + if (Z_TYPE(retval) != IS_UNDEF) { + if (Z_TYPE(retval) == IS_FALSE) { + _zend_error_cb_proxy(errtype, errfile, errline, "%s", errmsg); + } + zval_ptr_dtor(&retval); } - zval_ptr_dtor(&retval); + } else if (!EG(exception)) { + /* The user error handler failed, use built-in error handler */ + _zend_error_cb_proxy(errtype, errfile, errline, "%s", errmsg); } - } else if (!EG(exception)) { - /* The user error handler failed, use built-in error handler */ - zend_error_cb(type, error_filename, error_lineno, format, args); } if (in_compilation) {