From a80d1ee305431285301e5ef8abe7290fe4174361 Mon Sep 17 00:00:00 2001 From: Jacob Champion Date: Tue, 25 Aug 2026 08:34:50 -0700 Subject: [PATCH] libpq: Stop greasing protocol connections This reverts commit 4966bd3ed95e0d02bf220c4bad2b292963827dd4, which introduced the 19beta grease campaign, now that Beta 3 has been stamped. (The reservation and documentation for the grease version code, done in d8d7c5dc8f, remains.) Discussion: https://postgr.es/m/CAOYmi%2Bkqt_gn-wvUjJG1j3MM4LDDsRMURSPz2eMxfABu0iGtpw%40mail.gmail.com Backpatch-through: 19 --- doc/src/sgml/libpq.sgml | 17 ------ doc/src/sgml/protocol.sgml | 11 ---- src/interfaces/libpq/libpq-int.h | 1 - src/interfaces/libpq/fe-connect.c | 51 ++++-------------- src/interfaces/libpq/fe-misc.c | 18 ------- src/interfaces/libpq/fe-protocol3.c | 53 ++----------------- .../modules/libpq_pipeline/libpq_pipeline.c | 6 +-- 7 files changed, 16 insertions(+), 141 deletions(-) diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml index 123e7f03902..68487a3954f 100644 --- a/doc/src/sgml/libpq.sgml +++ b/doc/src/sgml/libpq.sgml @@ -2211,23 +2211,6 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname max_protocol_version - - - During the PostgreSQL 19 beta period, libpq connections that do not - specify a max_protocol_version will "grease" the - handshake by sending unsupported startup parameters, including version - 3.9999, in order to identify software that does not - correctly negotiate the connection. This replaces the default behavior - described below. - - - If you know that a server doesn't properly implement protocol version - negotiation, you can set max_protocol_version=3.0 to - revert to the standard behavior (preferably after notifying the server's - maintainers that their software needs to be fixed). - - - Specifies the protocol version to request from the server. The default is to use version 3.0 of the diff --git a/doc/src/sgml/protocol.sgml b/doc/src/sgml/protocol.sgml index 49f81676712..89ac680efd5 100644 --- a/doc/src/sgml/protocol.sgml +++ b/doc/src/sgml/protocol.sgml @@ -198,17 +198,6 @@ by default. - - - During the PostgreSQL 19 beta period, libpq will instead default to - requesting protocol version 3.9999, to test that servers and middleware - properly implement protocol version negotiation. Servers that support - negotiation will automatically downgrade to version 3.2 or 3.0. Users can - bypass this beta-only behavior by explicitly setting - max_protocol_version=3.0 in their connection string. - - - A single server can support multiple protocol versions. The initial startup-request message tells the server which protocol version the client diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h index a737d1db457..933ba0d99d5 100644 --- a/src/interfaces/libpq/libpq-int.h +++ b/src/interfaces/libpq/libpq-int.h @@ -965,7 +965,6 @@ 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 ee398f13998..ec98c58a407 100644 --- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -91,9 +91,8 @@ static int ldapServiceLookup(const char *purl, PQconninfoOption *options, /* This is part of the protocol so just define it */ #define ERRCODE_INVALID_PASSWORD "28P01" -/* These too */ +/* This too */ #define ERRCODE_CANNOT_CONNECT_NOW "57P03" -#define ERRCODE_PROTOCOL_VIOLATION "08P01" /* * Cope with the various platform-specific ways to spell TCP keepalive socket @@ -2150,13 +2149,15 @@ pqConnectOptions2(PGconn *conn) else { /* - * Default to PG_PROTOCOL_GREASE, which is larger than all real - * versions, to test negotiation. The server should automatically - * downgrade to a supported version. - * - * This behavior is for 19beta only. It will be reverted before RC1. + * To not break connecting to older servers/poolers that do not yet + * support NegotiateProtocolVersion, default to the 3.0 protocol at + * least for a while longer. Except when min_protocol_version is set + * to something larger, then we might as well default to the latest. */ - conn->max_pversion = PG_PROTOCOL_GREASE; + if (conn->min_pversion > PG_PROTOCOL(3, 0)) + conn->max_pversion = PG_PROTOCOL_LATEST; + else + conn->max_pversion = PG_PROTOCOL(3, 0); } if (conn->min_pversion > conn->max_pversion) @@ -4162,32 +4163,6 @@ keep_going: /* We will come back to here until there is /* Check to see if we should mention pgpassfile */ pgpassfileWarning(conn); - /* - * ...and whether we should mention grease. If the error - * message contains the PG_PROTOCOL_GREASE number (in - * major.minor, decimal, or hex format) or a complaint - * about a protocol violation before we've even started an - * authentication exchange, it's probably caused by a - * grease interaction. - */ - if (conn->max_pversion == PG_PROTOCOL_GREASE && - !conn->auth_req_received) - { - const char *sqlstate = PQresultErrorField(conn->result, - PG_DIAG_SQLSTATE); - - if ((sqlstate && - strcmp(sqlstate, ERRCODE_PROTOCOL_VIOLATION) == 0) || - (conn->errorMessage.len > 0 && - (strstr(conn->errorMessage.data, "3.9999") || - strstr(conn->errorMessage.data, "206607") || - strstr(conn->errorMessage.data, "3270F") || - strstr(conn->errorMessage.data, "3270f")))) - { - libpq_append_grease_info(conn); - } - } - CONNECTION_FAILED(); } /* Handle NegotiateProtocolVersion */ @@ -4418,14 +4393,6 @@ keep_going: /* We will come back to here until there is goto error_return; } - if (conn->max_pversion == PG_PROTOCOL_GREASE && - 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; - } - /* Almost there now ... */ conn->status = CONNECTION_CHECK_TARGET; goto keep_going; diff --git a/src/interfaces/libpq/fe-misc.c b/src/interfaces/libpq/fe-misc.c index 31bc436ac39..73d10e5cae5 100644 --- a/src/interfaces/libpq/fe-misc.c +++ b/src/interfaces/libpq/fe-misc.c @@ -1567,21 +1567,3 @@ 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", - "https://wiki.postgresql.org/wiki/Grease"); -} diff --git a/src/interfaces/libpq/fe-protocol3.c b/src/interfaces/libpq/fe-protocol3.c index 79099301abd..1fd427cb9be 100644 --- a/src/interfaces/libpq/fe-protocol3.c +++ b/src/interfaces/libpq/fe-protocol3.c @@ -1445,15 +1445,6 @@ pqGetNegotiateProtocolVersion3(PGconn *conn) { int their_version; int num; - 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; @@ -1514,7 +1505,6 @@ 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; } @@ -1522,12 +1512,9 @@ pqGetNegotiateProtocolVersion3(PGconn *conn) conn->pversion = their_version; /* - * Check that all expected unsupported parameters are reported by the - * server. + * We don't currently request any protocol extensions, so we don't expect + * the server to reply with any either. */ - found_test_protocol_negotiation = false; - expect_test_protocol_negotiation = (conn->max_pversion == PG_PROTOCOL_GREASE); - for (int i = 0; i < num; i++) { if (pqGets(&conn->workBuffer, conn)) @@ -1539,30 +1526,8 @@ pqGetNegotiateProtocolVersion3(PGconn *conn) libpq_append_conn_error(conn, "received invalid protocol negotiation message: server reported unsupported parameter name without a \"%s\" prefix (\"%s\")", "_pq_.", conn->workBuffer.data); goto failure; } - - /* Check if this is the expected test parameter */ - if (expect_test_protocol_negotiation && - strcmp(conn->workBuffer.data, "_pq_.test_protocol_negotiation") == 0) - { - found_test_protocol_negotiation = true; - } - else - { - libpq_append_conn_error(conn, "received invalid protocol negotiation message: server reported an unsupported parameter that was not requested (\"%s\")", - conn->workBuffer.data); - goto failure; - } - } - - /* - * If we requested protocol grease, the server must report - * _pq_.test_protocol_negotiation as unsupported. This ensures - * comprehensive NegotiateProtocolVersion implementation. - */ - if (expect_test_protocol_negotiation && !found_test_protocol_negotiation) - { - libpq_append_conn_error(conn, "server did not report the unsupported \"%s\" parameter in its protocol negotiation message", - "_pq_.test_protocol_negotiation"); + libpq_append_conn_error(conn, "received invalid protocol negotiation message: server reported an unsupported parameter that was not requested (\"%s\")", + conn->workBuffer.data); goto failure; } @@ -1571,8 +1536,6 @@ 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; @@ -2540,14 +2503,6 @@ build_startup_packet(const PGconn *conn, char *packet, if (conn->client_encoding_initial && conn->client_encoding_initial[0]) ADD_STARTUP_OPTION("client_encoding", conn->client_encoding_initial); - /* - * Add the test_protocol_negotiation option when greasing, to test that - * servers properly report unsupported protocol options in addition to - * unsupported minor versions. - */ - if (conn->pversion == PG_PROTOCOL_GREASE) - ADD_STARTUP_OPTION("_pq_.test_protocol_negotiation", ""); - /* Add any environment-driven GUC settings needed */ for (next_eo = options; next_eo->envName; next_eo++) { diff --git a/src/test/modules/libpq_pipeline/libpq_pipeline.c b/src/test/modules/libpq_pipeline/libpq_pipeline.c index 1660a68955e..ad007038dc9 100644 --- a/src/test/modules/libpq_pipeline/libpq_pipeline.c +++ b/src/test/modules/libpq_pipeline/libpq_pipeline.c @@ -1363,7 +1363,7 @@ test_protocol_version(PGconn *conn) Assert(max_protocol_version_index >= 0); /* - * Test default protocol_version (GREASE - should negotiate down to 3.2) + * Test default protocol_version */ vals[max_protocol_version_index] = ""; conn = PQconnectdbParams(keywords, vals, false); @@ -1373,8 +1373,8 @@ test_protocol_version(PGconn *conn) PQerrorMessage(conn)); protocol_version = PQfullProtocolVersion(conn); - if (protocol_version != 30002) - pg_fatal("expected 30002, got %d", protocol_version); + if (protocol_version != 30000) + pg_fatal("expected 30000, got %d", protocol_version); PQfinish(conn); -- 2.34.1