From e9b005158f689be47f318a544b236fd5c64a9ab3 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Mon, 31 May 2021 16:30:36 +0200 Subject: [PATCH] Fix output buffer discard on memory limit Move this code directly into the error handler, and check the heap->overflow flag. Discarding output here allows us to print the normal memory limit message to standard output. Otherwise nothing would be printed unless a different log medium was used, which makes for a suboptimal debugging experience. --- Zend/zend_alloc.c | 9 +++++++++ Zend/zend_alloc.h | 1 + main/main.c | 18 +++++------------- tests/lang/bug45392.phpt | 5 +---- 4 files changed, 16 insertions(+), 17 deletions(-) diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index 55c4258374f..75deafa6baa 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -2669,6 +2669,15 @@ ZEND_API zend_result zend_set_memory_limit(size_t memory_limit) return SUCCESS; } +ZEND_API bool zend_alloc_in_memory_limit_error_reporting(void) +{ +#if ZEND_MM_LIMIT + return AG(mm_heap)->overflow; +#else + return false; +#endif +} + ZEND_API size_t zend_memory_usage(bool real_usage) { #if ZEND_MM_STAT diff --git a/Zend/zend_alloc.h b/Zend/zend_alloc.h index 3af9b9446ae..9603af8a27d 100644 --- a/Zend/zend_alloc.h +++ b/Zend/zend_alloc.h @@ -220,6 +220,7 @@ ZEND_API void * __zend_realloc(void *p, size_t len) ZEND_ATTRIBUTE_ALLOC_SIZE(2) #define pestrdup_rel(s, persistent) ((persistent)?strdup(s):estrdup_rel(s)) ZEND_API zend_result zend_set_memory_limit(size_t memory_limit); +ZEND_API bool zend_alloc_in_memory_limit_error_reporting(void); ZEND_API void start_memory_manager(void); ZEND_API void shutdown_memory_manager(bool silent, bool full_shutdown); diff --git a/main/main.c b/main/main.c index ad7f680058b..cfd9b732fae 100644 --- a/main/main.c +++ b/main/main.c @@ -1235,6 +1235,10 @@ static ZEND_COLD void php_error_cb(int orig_type, zend_string *error_filename, c PG(last_error_lineno) = error_lineno; } + if (zend_alloc_in_memory_limit_error_reporting()) { + php_output_discard_all(); + } + /* display/log the error if necessary */ if (display && ((EG(error_reporting) & type) || (type & E_CORE)) && (PG(log_errors) || PG(display_errors) || (!module_initialized))) { @@ -1783,19 +1787,7 @@ void php_request_shutdown(void *dummy) /* 3. Flush all output buffers */ zend_try { - bool send_buffer = SG(request_info).headers_only ? 0 : 1; - - if (CG(unclean_shutdown) && PG(last_error_type) == E_ERROR && - (size_t)PG(memory_limit) < zend_memory_usage(1) - ) { - send_buffer = 0; - } - - if (!send_buffer) { - php_output_discard_all(); - } else { - php_output_end_all(); - } + php_output_end_all(); } zend_end_try(); /* 4. Reset max_execution_time (no longer executing php code after response sent) */ diff --git a/tests/lang/bug45392.phpt b/tests/lang/bug45392.phpt index 5940f7bc398..692fa0cdcf6 100644 --- a/tests/lang/bug45392.phpt +++ b/tests/lang/bug45392.phpt @@ -1,9 +1,5 @@ --TEST-- Bug #45392 (ob_start()/ob_end_clean() and memory_limit) ---INI-- -display_errors=stderr ---XFAIL-- -The issue has not yet been resolved. --SKIPIF-- --EXPECTF-- 2 + Fatal error: Allowed memory size of %d bytes exhausted%s