From b48ae226e6c31f5e1801e626d7602be7969f0fbd Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 13 Oct 2025 17:56:45 -0400 Subject: [PATCH] Fix incorrect message-printing in win32security.c. log_error() would probably fail completely if used, and would certainly print garbage for anything that needed to be interpolated into the message, because it was failing to use the correct printing subroutine for a va_list argument. This bug likely went undetected because the error cases this code is used for are rarely exercised - they only occur when Windows security API calls fail catastrophically (out of memory, security subsystem corruption, etc). The FRONTEND variant can be fixed just by calling vfprintf() instead of fprintf(). However, there was no va_list variant of write_stderr(), so create one by refactoring that function. Following the usual naming convention for such things, call it vwrite_stderr(). Author: Bryan Green Reviewed-by: Tom Lane Discussion: https://postgr.es/m/CAF+pBj8goe4fRmZ0V3Cs6eyWzYLvK+HvFLYEYWG=TzaM+tWPnw@mail.gmail.com Backpatch-through: 13 --- src/backend/utils/error/elog.c | 16 +++++++++++++--- src/include/utils/elog.h | 1 + src/port/win32security.c | 4 ++-- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c index dc0b74dc30b..d78f3ab8a30 100644 --- a/src/backend/utils/error/elog.c +++ b/src/backend/utils/error/elog.c @@ -3783,13 +3783,24 @@ write_stderr(const char *fmt,...) { va_list ap; + va_start(ap, fmt); + vwrite_stderr(fmt, ap); + va_end(ap); +} + + +/* + * Write errors to stderr (or by equal means when stderr is + * not available) - va_list version + */ +void +vwrite_stderr(const char *fmt, va_list ap) +{ #ifdef WIN32 char errbuf[2048]; /* Arbitrary size? */ #endif fmt = _(fmt); - - va_start(ap, fmt); #ifndef WIN32 /* On Unix, we just fprintf to stderr */ vfprintf(stderr, fmt, ap); @@ -3812,5 +3823,4 @@ write_stderr(const char *fmt,...) fflush(stderr); } #endif - va_end(ap); } diff --git a/src/include/utils/elog.h b/src/include/utils/elog.h index 675f4f5f469..581b39091e0 100644 --- a/src/include/utils/elog.h +++ b/src/include/utils/elog.h @@ -527,5 +527,6 @@ extern void write_jsonlog(ErrorData *edata); * safely (memory context, GUC load etc) */ extern void write_stderr(const char *fmt,...) pg_attribute_printf(1, 2); +extern void vwrite_stderr(const char *fmt, va_list ap) pg_attribute_printf(1, 0); #endif /* ELOG_H */ diff --git a/src/port/win32security.c b/src/port/win32security.c index a46b82dd048..b7608ab1706 100644 --- a/src/port/win32security.c +++ b/src/port/win32security.c @@ -31,9 +31,9 @@ log_error(const char *fmt,...) va_start(ap, fmt); #ifndef FRONTEND - write_stderr(fmt, ap); + vwrite_stderr(fmt, ap); #else - fprintf(stderr, fmt, ap); + vfprintf(stderr, fmt, ap); #endif va_end(ap); }