On 2/20/19 11:24 AM, Tom Lane wrote: > Pierre Ducroquet <p.p...@pinaraf.info> writes: >> For simple functions like enum_eq/enum_ne, marking them leakproof is an >> obvious fix (patch attached to this email, including also textin/textout). > > This is not nearly as "obvious" as you think. See prior discussions, > notably > https://www.postgresql.org/message-id/flat/31042.1546194242%40sss.pgh.pa.us > > Up to now we've taken a very strict definition of what leakproofness > means; as Noah stated, if a function can throw errors for some inputs, > it's not considered leakproof, even if those inputs should never be > encountered in practice. Most of the things we've been willing to > mark leakproof are straight-line code that demonstrably can't throw > any errors at all. > > The previous thread seemed to have consensus that the hazards in > text_cmp and friends were narrow enough that nobody had a practical > problem with marking them leakproof --- but we couldn't define an > objective policy statement that would allow making such decisions, > so nothing's been changed as yet. I think it is important to have > an articulable policy about this, not just a seat-of-the-pants > conclusion about the risk level in a particular function.
What if we provided an option to redact all client messages (leaving logged messages as-is). Separately we could provide a GUC to force all functions to be resolved as leakproof. Depending on your requirements, having both options turned on could be perfectly acceptable. Patch for discussion attached. Joe -- Crunchy Data - http://crunchydata.com PostgreSQL Support for Secure Enterprises Consulting, Training, & Open Source Development
diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c index e88c45d..8c32d6c 100644 *** a/src/backend/utils/cache/lsyscache.c --- b/src/backend/utils/cache/lsyscache.c *************** *** 46,51 **** --- 46,54 ---- #include "utils/syscache.h" #include "utils/typcache.h" + /* GUC to force functions to be treated as leakproof */ + extern bool force_leakproof; + /* Hook for plugins to get control in get_attavgwidth() */ get_attavgwidth_hook_type get_attavgwidth_hook = NULL; *************** get_func_leakproof(Oid funcid) *** 1595,1600 **** --- 1598,1610 ---- HeapTuple tp; bool result; + /* + * If client message suppression was requested, + * treat all functions as leakproof + */ + if (force_leakproof) + return true; + tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid)); if (!HeapTupleIsValid(tp)) elog(ERROR, "cache lookup failed for function %u", funcid); diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c index 8b4720e..9941756 100644 *** a/src/backend/utils/error/elog.c --- b/src/backend/utils/error/elog.c *************** int Log_destination = LOG_DESTINATION_ *** 107,112 **** --- 107,113 ---- char *Log_destination_string = NULL; bool syslog_sequence_numbers = true; bool syslog_split_messages = true; + bool suppress_client_messages = false; #ifdef HAVE_SYSLOG *************** send_message_to_frontend(ErrorData *edat *** 3166,3189 **** /* M field is required per protocol, so always send something */ pq_sendbyte(&msgbuf, PG_DIAG_MESSAGE_PRIMARY); - if (edata->message) - err_sendstring(&msgbuf, edata->message); - else - err_sendstring(&msgbuf, _("missing error text")); ! if (edata->detail) { ! pq_sendbyte(&msgbuf, PG_DIAG_MESSAGE_DETAIL); ! err_sendstring(&msgbuf, edata->detail); ! } ! /* detail_log is intentionally not used here */ ! if (edata->hint) ! { ! pq_sendbyte(&msgbuf, PG_DIAG_MESSAGE_HINT); ! err_sendstring(&msgbuf, edata->hint); } if (edata->context) { --- 3167,3197 ---- /* M field is required per protocol, so always send something */ pq_sendbyte(&msgbuf, PG_DIAG_MESSAGE_PRIMARY); ! /* skip sending if requested */ ! if (!suppress_client_messages) { ! if (edata->message) ! err_sendstring(&msgbuf, edata->message); ! else ! err_sendstring(&msgbuf, _("missing error text")); ! if (edata->detail) ! { ! pq_sendbyte(&msgbuf, PG_DIAG_MESSAGE_DETAIL); ! err_sendstring(&msgbuf, edata->detail); ! } ! /* detail_log is intentionally not used here */ ! ! if (edata->hint) ! { ! pq_sendbyte(&msgbuf, PG_DIAG_MESSAGE_HINT); ! err_sendstring(&msgbuf, edata->hint); ! } } + else + err_sendstring(&msgbuf, _("redacted message text")); if (edata->context) { *************** send_message_to_frontend(ErrorData *edat *** 3274,3283 **** if (edata->show_funcname && edata->funcname) appendStringInfo(&buf, "%s: ", edata->funcname); ! if (edata->message) ! appendStringInfoString(&buf, edata->message); else ! appendStringInfoString(&buf, _("missing error text")); if (edata->cursorpos > 0) appendStringInfo(&buf, _(" at character %d"), --- 3282,3297 ---- if (edata->show_funcname && edata->funcname) appendStringInfo(&buf, "%s: ", edata->funcname); ! /* skip sending if requested */ ! if (!suppress_client_messages) ! { ! if (edata->message) ! appendStringInfoString(&buf, edata->message); ! else ! appendStringInfoString(&buf, _("missing error text")); ! } else ! appendStringInfoString(&buf, _("redacted message text")); if (edata->cursorpos > 0) appendStringInfo(&buf, _(" at character %d"), diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 156d147..e8a1617 100644 *** a/src/backend/utils/misc/guc.c --- b/src/backend/utils/misc/guc.c *************** char *event_source; *** 495,500 **** --- 495,501 ---- bool row_security; bool check_function_bodies = true; + bool force_leakproof; /* * This GUC exists solely for backward compatibility, check its definition for *************** static struct config_bool ConfigureNames *** 1911,1916 **** --- 1912,1935 ---- false, NULL, NULL, NULL }, + + { + {"suppress_client_messages", PGC_POSTMASTER, ERROR_HANDLING_OPTIONS, + gettext_noop("Suppress all client messages."), + }, + &suppress_client_messages, + false, + NULL, NULL, NULL + }, + + { + {"force_leakproof", PGC_POSTMASTER, ERROR_HANDLING_OPTIONS, + gettext_noop("Force all functions to behave as if leakproof."), + }, + &force_leakproof, + false, + NULL, NULL, NULL + }, /* End-of-list marker */ { diff --git a/src/include/utils/elog.h b/src/include/utils/elog.h index 7ac37fd..11e9897 100644 *** a/src/include/utils/elog.h --- b/src/include/utils/elog.h *************** extern int Log_destination; *** 407,412 **** --- 407,413 ---- extern char *Log_destination_string; extern bool syslog_sequence_numbers; extern bool syslog_split_messages; + extern bool suppress_client_messages; /* Log destination bitmap */ #define LOG_DESTINATION_STDERR 1
signature.asc
Description: OpenPGP digital signature