Do not hardcode PG_PROTOCOL_LATEST in NegotiateProtocolVersion

We shouldn't ask the client to use a protocol version later than the
one that they requested. To avoid that, if the client requests a
version newer than the latest one we support, set FrontendProtocol
to the latest version we support, not the requested version. Then,
use that value when building the NegotiateProtocolVersion message.
(It seems good on general principle to avoid setting FrontendProtocol
to a version we don't support, anyway.)

None of this really matters right now, because we only support a
single protocol version, but if that ever changes, we'll need this.

Jelte Fennema-Nio, reviewed by me and incorporating some of my
proposed wording

Discussion: https://postgr.es/m/CAGECzQTyXDNtMXdq2L-Wp=OvOCPa07r6+U_MGb==h90MrfT+fQ@mail.gmail.com
This commit is contained in:
Robert Haas 2024-08-15 10:44:15 -04:00
parent 8dc28d7eb8
commit 516b87502d
1 changed files with 13 additions and 6 deletions

View File

@ -690,9 +690,13 @@ ProcessStartupPacket(Port *port, bool ssl_done, bool gss_done)
/* /*
* Set FrontendProtocol now so that ereport() knows what format to send if * Set FrontendProtocol now so that ereport() knows what format to send if
* we fail during startup. * we fail during startup. We use the protocol version requested by the
* client unless it's higher than the latest version we support. It's
* possible that error message fields might look different in newer
* protocol versions, but that's something those new clients should be
* able to deal with.
*/ */
FrontendProtocol = proto; FrontendProtocol = Min(proto, PG_PROTOCOL_LATEST);
/* Check that the major protocol version is in range. */ /* Check that the major protocol version is in range. */
if (PG_PROTOCOL_MAJOR(proto) < PG_PROTOCOL_MAJOR(PG_PROTOCOL_EARLIEST) || if (PG_PROTOCOL_MAJOR(proto) < PG_PROTOCOL_MAJOR(PG_PROTOCOL_EARLIEST) ||
@ -852,9 +856,12 @@ ProcessStartupPacket(Port *port, bool ssl_done, bool gss_done)
/* /*
* Send a NegotiateProtocolVersion to the client. This lets the client know * Send a NegotiateProtocolVersion to the client. This lets the client know
* that they have requested a newer minor protocol version than we are able * that they have either requested a newer minor protocol version than we are
* to speak. We'll speak the highest version we know about; the client can, * able to speak, or at least one protocol option that we don't understand, or
* of course, abandon the connection if that's a problem. * possibly both. FrontendProtocol has already been set to the version
* requested by the client or the highest version we know how to speak,
* whichever is older. If the highest version that we know how to speak is too
* old for the client, it can abandon the connection.
* *
* We also include in the response a list of protocol options we didn't * We also include in the response a list of protocol options we didn't
* understand. This allows clients to include optional parameters that might * understand. This allows clients to include optional parameters that might
@ -870,7 +877,7 @@ SendNegotiateProtocolVersion(List *unrecognized_protocol_options)
ListCell *lc; ListCell *lc;
pq_beginmessage(&buf, PqMsg_NegotiateProtocolVersion); pq_beginmessage(&buf, PqMsg_NegotiateProtocolVersion);
pq_sendint32(&buf, PG_PROTOCOL_LATEST); pq_sendint32(&buf, FrontendProtocol);
pq_sendint32(&buf, list_length(unrecognized_protocol_options)); pq_sendint32(&buf, list_length(unrecognized_protocol_options));
foreach(lc, unrecognized_protocol_options) foreach(lc, unrecognized_protocol_options)
pq_sendstring(&buf, lfirst(lc)); pq_sendstring(&buf, lfirst(lc));