v7-0002-squash-libpq-Grease-the-protocol-by-default.patch
application/octet-stream
Filename: v7-0002-squash-libpq-Grease-the-protocol-by-default.patch
Type: application/octet-stream
Part: 1
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v7-0002
Subject: squash! libpq: Grease the protocol by default
| File | + | − |
|---|---|---|
| src/interfaces/libpq/fe-connect.c | 1 | 0 |
| src/interfaces/libpq/fe-misc.c | 19 | 0 |
| src/interfaces/libpq/fe-protocol3.c | 10 | 0 |
| src/interfaces/libpq/libpq-int.h | 1 | 0 |
From e8bc0d2acfcc036b7b6c22454118464d9c500a12 Mon Sep 17 00:00:00 2001
From: Jacob Champion <jacob.champion@enterprisedb.com>
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