From 2cde4b2ea46129f7a11ac6c6234dd4691e05a8f3 Mon Sep 17 00:00:00 2001
From: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
Date: Mon, 15 Jan 2024 20:21:30 +0100
Subject: [PATCH] Fix GH-13097: Anonymous class reference in trigger_error /
thrown Exception
Closes GH-13153.
---
NEWS | 2 ++
Zend/tests/gh13097_a.phpt | 15 +++++++++++++++
Zend/tests/gh13097_b.phpt | 18 ++++++++++++++++++
Zend/zend_builtin_functions.c | 7 +++----
Zend/zend_exceptions.c | 3 ++-
main/main.c | 12 +++++++++---
6 files changed, 49 insertions(+), 8 deletions(-)
create mode 100644 Zend/tests/gh13097_a.phpt
create mode 100644 Zend/tests/gh13097_b.phpt
diff --git a/NEWS b/NEWS
index c826604c07f..5509955c51c 100644
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,8 @@ PHP NEWS
- Core:
. Fixed timer leak in zend-max-execution-timers builds. (withinboredom)
. Fixed bug GH-12349 (linking failure on ARM with mold). (Jan Palus)
+ . Fixed bug GH-13097 (Anonymous class reference in trigger_error / thrown
+ Exception). (nielsdos)
- Curl:
. Fix missing error check in curl_multi_init(). (divinity76)
diff --git a/Zend/tests/gh13097_a.phpt b/Zend/tests/gh13097_a.phpt
new file mode 100644
index 00000000000..b9ad729f66e
--- /dev/null
+++ b/Zend/tests/gh13097_a.phpt
@@ -0,0 +1,15 @@
+--TEST--
+GH-13097 (Anonymous class reference in trigger_error / thrown Exception)
+--FILE--
+
+--EXPECTF--
+Fatal error: class@anonymous%s ...now you don't! in %s on line %d
diff --git a/Zend/tests/gh13097_b.phpt b/Zend/tests/gh13097_b.phpt
new file mode 100644
index 00000000000..7473c99d9f4
--- /dev/null
+++ b/Zend/tests/gh13097_b.phpt
@@ -0,0 +1,18 @@
+--TEST--
+GH-13097 (Anonymous class reference in trigger_error / thrown Exception)
+--FILE--
+
+--EXPECTF--
+Fatal error: Uncaught Exception: class@anonymous%s ...now you don't! in %s:%d
+Stack trace:
+#0 {main}
+ thrown in %s on line %d
diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c
index 9c4b836cafa..72cb07decbd 100644
--- a/Zend/zend_builtin_functions.c
+++ b/Zend/zend_builtin_functions.c
@@ -1108,10 +1108,9 @@ ZEND_FUNCTION(get_included_files)
ZEND_FUNCTION(trigger_error)
{
zend_long error_type = E_USER_NOTICE;
- char *message;
- size_t message_len;
+ zend_string *message;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &message, &message_len, &error_type) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|l", &message, &error_type) == FAILURE) {
RETURN_THROWS();
}
@@ -1128,7 +1127,7 @@ ZEND_FUNCTION(trigger_error)
break;
}
- zend_error((int)error_type, "%s", message);
+ zend_error_zstr_at(error_type, zend_get_executed_filename_ex(), zend_get_executed_lineno(), message);
// TODO Change to void
RETURN_TRUE;
}
diff --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c
index 2b2f6dfb4b3..8ad603e51e7 100644
--- a/Zend/zend_exceptions.c
+++ b/Zend/zend_exceptions.c
@@ -950,9 +950,10 @@ ZEND_API ZEND_COLD zend_result zend_exception_error(zend_object *ex, int severit
file = zval_get_string(GET_PROPERTY_SILENT(&exception, ZEND_STR_FILE));
line = zval_get_long(GET_PROPERTY_SILENT(&exception, ZEND_STR_LINE));
+ ZVAL_STR(&tmp, str);
zend_error_va(severity | E_DONT_BAIL,
(file && ZSTR_LEN(file) > 0) ? file : NULL, line,
- "Uncaught %s\n thrown", ZSTR_VAL(str));
+ "Uncaught %Z\n thrown", &tmp);
zend_string_release_ex(str, 0);
zend_string_release_ex(file, 0);
diff --git a/main/main.c b/main/main.c
index b2d03b4af8a..83f8829890e 100644
--- a/main/main.c
+++ b/main/main.c
@@ -1350,19 +1350,25 @@ static ZEND_COLD void php_error_cb(int orig_type, zend_string *error_filename, c
php_printf("%s
\n%s: %s in %s on line %" PRIu32 "
\n%s", STR_PRINT(prepend_string), error_type_str, ZSTR_VAL(buf), ZSTR_VAL(error_filename), error_lineno, STR_PRINT(append_string));
zend_string_free(buf);
} else {
- php_printf("%s
\n%s: %s in %s on line %" PRIu32 "
\n%s", STR_PRINT(prepend_string), error_type_str, ZSTR_VAL(message), ZSTR_VAL(error_filename), error_lineno, STR_PRINT(append_string));
+ zval tmp;
+ ZVAL_STR(&tmp, message);
+ php_printf_unchecked("%s
\n%s: %Z in %s on line %" PRIu32 "
\n%s", STR_PRINT(prepend_string), error_type_str, &tmp, ZSTR_VAL(error_filename), error_lineno, STR_PRINT(append_string));
}
} else {
/* Write CLI/CGI errors to stderr if display_errors = "stderr" */
if ((!strcmp(sapi_module.name, "cli") || !strcmp(sapi_module.name, "cgi") || !strcmp(sapi_module.name, "phpdbg")) &&
PG(display_errors) == PHP_DISPLAY_ERRORS_STDERR
) {
- fprintf(stderr, "%s: %s in %s on line %" PRIu32 "\n", error_type_str, ZSTR_VAL(message), ZSTR_VAL(error_filename), error_lineno);
+ fprintf(stderr, "%s: ", error_type_str);
+ fwrite(ZSTR_VAL(message), sizeof(char), ZSTR_LEN(message), stderr);
+ fprintf(stderr, " in %s on line %" PRIu32 "\n", ZSTR_VAL(error_filename), error_lineno);
#ifdef PHP_WIN32
fflush(stderr);
#endif
} else {
- php_printf("%s\n%s: %s in %s on line %" PRIu32 "\n%s", STR_PRINT(prepend_string), error_type_str, ZSTR_VAL(message), ZSTR_VAL(error_filename), error_lineno, STR_PRINT(append_string));
+ zval tmp;
+ ZVAL_STR(&tmp, message);
+ php_printf_unchecked("%s\n%s: %Z in %s on line %" PRIu32 "\n%s", STR_PRINT(prepend_string), error_type_str, &tmp, ZSTR_VAL(error_filename), error_lineno, STR_PRINT(append_string));
}
}
}