postgres.git / summary / log / commit / refs

commit    9883e3cd1c61b1bf23d655e62789ff56c3da3bb5
Author:   Tom Lane <tgl@sss.pgh.pa.us>
Date:     Mon Oct 13 21:56:45 2025 +0000
First released in: 13.23, 14.20, 15.15, 16.11, 17.7, 18.1

    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 <dbryan.green@gmail.com>
    Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
    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 155d8519a74..4f99f701ea5 100644 --- a/src/backend/utils/error/elog.c +++ b/src/backend/utils/error/elog.c @@ -3734,13 +3734,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); @@ -3763,7 +3774,6 @@ 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 8bb55e5b3cc..b3e95044174 100644 --- a/src/include/utils/elog.h +++ b/src/include/utils/elog.h @@ -536,6 +536,7 @@ 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); /* * Write a message to STDERR using only async-signal-safe functions. This can diff --git a/src/port/win32security.c b/src/port/win32security.c index 4d9d28c0d7f..346d86e6f88 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); } [parent: 0a47f054ef8d]