From e8bc0d2acfcc036b7b6c22454118464d9c500a12 Mon Sep 17 00:00:00 2001 From: Jacob Champion Date: Fri, 6 Feb 2026 14:23:31 -0800 Subject: [PATCH v7 2/2] squash! libpq: Grease the protocol by default Add more information to help a user who hits a grease failure. Still needs a final URL. --- src/interfaces/libpq/libpq-int.h | 1 + src/interfaces/libpq/fe-connect.c | 1 + src/interfaces/libpq/fe-misc.c | 19 +++++++++++++++++++ src/interfaces/libpq/fe-protocol3.c | 10 ++++++++++ 4 files changed, 31 insertions(+) diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h index fb6a7cbf15d..bd7eb59f5f8 100644 --- a/src/interfaces/libpq/libpq-int.h +++ b/src/interfaces/libpq/libpq-int.h @@ -958,6 +958,7 @@ extern char *libpq_ngettext(const char *msgid, const char *msgid_plural, unsigne extern void libpq_append_error(PQExpBuffer errorMessage, const char *fmt,...) pg_attribute_printf(2, 3); extern void libpq_append_conn_error(PGconn *conn, const char *fmt,...) pg_attribute_printf(2, 3); +extern void libpq_append_grease_info(PGconn *conn); /* * These macros are needed to let error-handling code be portable between diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index c42f38cbc99..418c71a9aa8 100644 --- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -4388,6 +4388,7 @@ keep_going: /* We will come back to here until there is conn->pversion == PG_PROTOCOL_GREASE) { libpq_append_conn_error(conn, "server incorrectly accepted \"grease\" protocol version 3.9999 without negotiation"); + libpq_append_grease_info(conn); goto error_return; } diff --git a/src/interfaces/libpq/fe-misc.c b/src/interfaces/libpq/fe-misc.c index 5e54353fbfe..e749aac6783 100644 --- a/src/interfaces/libpq/fe-misc.c +++ b/src/interfaces/libpq/fe-misc.c @@ -1423,3 +1423,22 @@ libpq_append_conn_error(PGconn *conn, const char *fmt,...) appendPQExpBufferChar(&conn->errorMessage, '\n'); } + +/* + * For 19beta only, some protocol errors will have additional information + * appended to help with the "grease" campaign. + */ +void +libpq_append_grease_info(PGconn *conn) +{ + /* translator: %s is a URL */ + libpq_append_conn_error(conn, + "\tThis indicates a bug in either the server being contacted\n" + "\tor a proxy handling the connection. Please consider\n" + "\treporting this to the maintainers of that software.\n" + "\tFor more information, including instructions on how to\n" + "\twork around this issue for now, visit\n" + "\t\t%s", + /* TODO */ + "https://www.postgresql.org/docs/devel/libpq-connect.html#LIBPQ-CONNECT-MAX-PROTOCOL-VERSION"); +} diff --git a/src/interfaces/libpq/fe-protocol3.c b/src/interfaces/libpq/fe-protocol3.c index fc011e89450..8c1fda5caf0 100644 --- a/src/interfaces/libpq/fe-protocol3.c +++ b/src/interfaces/libpq/fe-protocol3.c @@ -1447,6 +1447,13 @@ pqGetNegotiateProtocolVersion3(PGconn *conn) bool found_test_protocol_negotiation; bool expect_test_protocol_negotiation; + /* + * During 19beta only, if protocol grease is in use, assume that it's the + * cause of any invalid messages encountered below. We'll print extra + * information for the end user in that case. + */ + bool need_grease_info = (conn->max_pversion == PG_PROTOCOL_GREASE); + if (pqGetInt(&their_version, 4, conn) != 0) goto eof; @@ -1506,6 +1513,7 @@ pqGetNegotiateProtocolVersion3(PGconn *conn) PG_PROTOCOL_MAJOR(conn->min_pversion), PG_PROTOCOL_MINOR(conn->min_pversion)); + need_grease_info = false; /* this is valid server behavior */ goto failure; } @@ -1561,6 +1569,8 @@ pqGetNegotiateProtocolVersion3(PGconn *conn) eof: libpq_append_conn_error(conn, "received invalid protocol negotiation message: message too short"); failure: + if (need_grease_info) + libpq_append_grease_info(conn); conn->asyncStatus = PGASYNC_READY; pqSaveErrorResult(conn); return 1; -- 2.34.1