From c8e8b5a6e20bf471d83059aebe64bca16f184057 Mon Sep 17 00:00:00 2001 From: Robert Haas Date: Fri, 21 Oct 2011 13:26:40 -0400 Subject: Try to log current the query string when a backend crashes. To avoid minimize risk inside the postmaster, we subject this feature to a number of significant limitations. We very much wish to avoid doing any complex processing inside the postmaster, due to the posssibility that the crashed backend has completely corrupted shared memory. To that end, no encoding conversion is done; instead, we just replace anything that doesn't look like an ASCII character with a question mark. We limit the amount of data copied to 1024 characters, and carefully sanity check the source of that data. While these restrictions would doubtless be unacceptable in a general-purpose logging facility, even this limited facility seems like an improvement over the status quo ante. Marti Raudsepp, reviewed by PDXPUG and myself --- src/backend/utils/adt/ascii.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'src/backend/utils/adt/ascii.c') diff --git a/src/backend/utils/adt/ascii.c b/src/backend/utils/adt/ascii.c index 7ecf4949b5f..7c9e96a04f6 100644 --- a/src/backend/utils/adt/ascii.c +++ b/src/backend/utils/adt/ascii.c @@ -158,3 +158,37 @@ to_ascii_default(PG_FUNCTION_ARGS) PG_RETURN_TEXT_P(encode_to_ascii(data, enc)); } + +/* ---------- + * "Escape" a string in unknown encoding to a valid ASCII string. + * Replace non-ASCII bytes with '?' + * This must not trigger ereport(ERROR), as it is called from postmaster. + * + * Unlike C strncpy(), the result is always terminated with exactly one null + * byte. + * ---------- + */ +void +ascii_safe_strncpy(char *dest, const char *src, int len) +{ + int i; + + for (i = 0; i < (len - 1); i++) + { + unsigned char ch = src[i]; /* use unsigned char here to avoid compiler warning */ + + if (ch == '\0') + break; + /* Keep printable ASCII characters */ + if (32 <= ch && ch <= 127) + dest[i] = ch; + /* White-space is also OK */ + else if (ch == '\n' || ch == '\r' || ch == '\t') + dest[i] = ch; + /* Everything else is replaced with '?' */ + else + dest[i] = '?'; + } + + dest[i] = '\0'; +} -- cgit v1.2.3