From 026fe1ad69204a7fd26eca8a7a938a7ef22a14c1 Mon Sep 17 00:00:00 2001 From: Reeze Xia Date: Thu, 22 Jan 2015 23:57:09 +0800 Subject: [PATCH 1/3] Implemented FR: Allow error_handler's errmsg parameter to be passed by reference --- Zend/tests/errmsg_046.phpt | 27 +++++++++++++++++++++++++++ Zend/tests/errmsg_047.phpt | 21 +++++++++++++++++++++ Zend/tests/errmsg_048.phpt | 17 +++++++++++++++++ Zend/zend.c | 28 ++++++++++++++++++++-------- 4 files changed, 85 insertions(+), 8 deletions(-) create mode 100644 Zend/tests/errmsg_046.phpt create mode 100644 Zend/tests/errmsg_047.phpt create mode 100644 Zend/tests/errmsg_048.phpt diff --git a/Zend/tests/errmsg_046.phpt b/Zend/tests/errmsg_046.phpt new file mode 100644 index 0000000000000..be60e31b67681 --- /dev/null +++ b/Zend/tests/errmsg_046.phpt @@ -0,0 +1,27 @@ +--TEST-- +Allow error handler declare referenced $errmsg parameter 01 +--FILE-- + +--EXPECTF-- +Notice: [Prefix] - Undefined variable: undefined - [Suffix] in %s on line %d +array(4) { + ["type"]=> + int(8) + ["message"]=> + string(51) "[Prefix] - Undefined variable: undefined - [Suffix]" + ["file"]=> + string(%d) "%s" + ["line"]=> + int(%d) +} diff --git a/Zend/tests/errmsg_047.phpt b/Zend/tests/errmsg_047.phpt new file mode 100644 index 0000000000000..c1f6df38c5d42 --- /dev/null +++ b/Zend/tests/errmsg_047.phpt @@ -0,0 +1,21 @@ +--TEST-- +Allow error handler declare referenced $errmsg parameter with exception +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught exception 'Exception' with message 'exception from handler' in %s:%d +Stack trace: +#0 %s(%d): {closure}(8, '[Prefix] - Unde...', '%s', %s, Array) +#1 {main} + thrown in %s on line %d diff --git a/Zend/tests/errmsg_048.phpt b/Zend/tests/errmsg_048.phpt new file mode 100644 index 0000000000000..e038cedf8e931 --- /dev/null +++ b/Zend/tests/errmsg_048.phpt @@ -0,0 +1,17 @@ +--TEST-- +Allow error handler declare referenced $errmsg parameter with wrong data type +--FILE-- + +--EXPECTF-- +Notice: Array to string conversion in %s on line %d + +Notice: Array in %s on line %d diff --git a/Zend/zend.c b/Zend/zend.c index dcc95a851a688..cb86480e031b1 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -1145,16 +1145,28 @@ 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); + + { + va_list empty_va_list; + int result = call_user_function_ex(CG(function_table), NULL, &orig_user_error_handler, &retval, 5, params, 1, NULL); + zval *errmsg = ¶ms[1]; + + if (Z_TYPE_P(errmsg) == IS_REFERENCE) { + errmsg = Z_REFVAL_P(errmsg); + convert_to_string(errmsg); + } + + if (result == SUCCESS) { + if (Z_TYPE(retval) != IS_UNDEF) { + if (Z_TYPE(retval) == IS_FALSE) { + zend_error_cb(type, error_filename, error_lineno, Z_STR_P(errmsg)->val, empty_va_list); + } + 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(type, error_filename, error_lineno, Z_STR_P(errmsg)->val, empty_va_list); } - } 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) { From 041cf62123038df4fe9f37ddc4bbc221c6f91525 Mon Sep 17 00:00:00 2001 From: Reeze Xia Date: Fri, 23 Jan 2015 00:11:59 +0800 Subject: [PATCH 2/3] Use defined macro instead of hand comparation --- Zend/zend.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zend/zend.c b/Zend/zend.c index cb86480e031b1..d943921d20b6d 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -1151,7 +1151,7 @@ static void zend_error_va_list(int type, const char *format, va_list args) int result = call_user_function_ex(CG(function_table), NULL, &orig_user_error_handler, &retval, 5, params, 1, NULL); zval *errmsg = ¶ms[1]; - if (Z_TYPE_P(errmsg) == IS_REFERENCE) { + if (Z_ISREF_P(errmsg)) { errmsg = Z_REFVAL_P(errmsg); convert_to_string(errmsg); } From e6faf900099a044217caa4d711811c3d123faa96 Mon Sep 17 00:00:00 2001 From: Reeze Xia Date: Fri, 23 Jan 2015 17:43:21 +0800 Subject: [PATCH 3/3] Allow the first four parameters of error handler to be passed by reference --- Zend/tests/errmsg_046.phpt | 27 ----------- Zend/tests/errmsg_048.phpt | 17 ------- Zend/tests/error_handler_001.phpt | 30 ++++++++++++ ...errmsg_047.phpt => error_handler_002.phpt} | 12 +++-- Zend/tests/error_handler_003.phpt | 34 ++++++++++++++ Zend/zend.c | 46 ++++++++++++++++--- 6 files changed, 111 insertions(+), 55 deletions(-) delete mode 100644 Zend/tests/errmsg_046.phpt delete mode 100644 Zend/tests/errmsg_048.phpt create mode 100644 Zend/tests/error_handler_001.phpt rename Zend/tests/{errmsg_047.phpt => error_handler_002.phpt} (50%) create mode 100644 Zend/tests/error_handler_003.phpt diff --git a/Zend/tests/errmsg_046.phpt b/Zend/tests/errmsg_046.phpt deleted file mode 100644 index be60e31b67681..0000000000000 --- a/Zend/tests/errmsg_046.phpt +++ /dev/null @@ -1,27 +0,0 @@ ---TEST-- -Allow error handler declare referenced $errmsg parameter 01 ---FILE-- - ---EXPECTF-- -Notice: [Prefix] - Undefined variable: undefined - [Suffix] in %s on line %d -array(4) { - ["type"]=> - int(8) - ["message"]=> - string(51) "[Prefix] - Undefined variable: undefined - [Suffix]" - ["file"]=> - string(%d) "%s" - ["line"]=> - int(%d) -} diff --git a/Zend/tests/errmsg_048.phpt b/Zend/tests/errmsg_048.phpt deleted file mode 100644 index e038cedf8e931..0000000000000 --- a/Zend/tests/errmsg_048.phpt +++ /dev/null @@ -1,17 +0,0 @@ ---TEST-- -Allow error handler declare referenced $errmsg parameter with wrong data type ---FILE-- - ---EXPECTF-- -Notice: Array to string conversion in %s on line %d - -Notice: Array in %s on line %d 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/errmsg_047.phpt b/Zend/tests/error_handler_002.phpt similarity index 50% rename from Zend/tests/errmsg_047.phpt rename to Zend/tests/error_handler_002.phpt index c1f6df38c5d42..3b4ce756b0355 100644 --- a/Zend/tests/errmsg_047.phpt +++ b/Zend/tests/error_handler_002.phpt @@ -1,21 +1,25 @@ --TEST-- -Allow error handler declare referenced $errmsg parameter with exception +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}(8, '[Prefix] - Unde...', '%s', %s, Array) +#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 d943921d20b6d..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 */ @@ -1147,25 +1159,45 @@ static void zend_error_va_list(int type, const char *format, va_list args) ZVAL_UNDEF(&retval); { - va_list empty_va_list; int result = call_user_function_ex(CG(function_table), NULL, &orig_user_error_handler, &retval, 5, params, 1, NULL); - zval *errmsg = ¶ms[1]; + 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(errmsg)) { - errmsg = Z_REFVAL_P(errmsg); - convert_to_string(errmsg); + 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(type, error_filename, error_lineno, Z_STR_P(errmsg)->val, empty_va_list); + _zend_error_cb_proxy(errtype, errfile, errline, "%s", errmsg); } zval_ptr_dtor(&retval); } } else if (!EG(exception)) { /* The user error handler failed, use built-in error handler */ - zend_error_cb(type, error_filename, error_lineno, Z_STR_P(errmsg)->val, empty_va_list); + _zend_error_cb_proxy(errtype, errfile, errline, "%s", errmsg); } }