v4-0003-libpq-Be-strict-about-cancel-key-lengths.patch
text/x-patch
Filename: v4-0003-libpq-Be-strict-about-cancel-key-lengths.patch
Type: text/x-patch
Part: 2
Message:
Re: BackendKeyData is mandatory?
Patch
Format: format-patch
Series: patch v4-0003
Subject: libpq: Be strict about cancel key lengths
| File | + | − |
|---|---|---|
| doc/src/sgml/protocol.sgml | 1 | 1 |
| src/interfaces/libpq/fe-protocol3.c | 21 | 0 |
From 63d0649e95e31ede89cc70d13fd880c4fbc1e2ac Mon Sep 17 00:00:00 2001
From: Heikki Linnakangas <heikki.linnakangas@iki.fi>
Date: Thu, 14 Aug 2025 14:28:49 +0300
Subject: [PATCH v4 3/3] libpq: Be strict about cancel key lengths
The protocol documentation states that the maximum length of a cancel
key is 256 bytes. This starts checking for that limit in
libpq. Otherwise third party backend implementations will probably
start using more bytes anyway. We also start requiring that a protocol
3.0 connection does not send a longer cancel key, to make sure that
servers don't start breaking old 3.0-only clients by accident. Finally
this also restricts the minimum key length to 4 bytes (both in the
protocol spec and in the libpq implementation).
Author: Jelte Fennema-Nio <postgres@jeltef.nl>
Discussion: https://www.postgresql.org/message-id/DAVFE8ECY631.1KKWX7L8S4DAQ@jeltef.nl
---
doc/src/sgml/protocol.sgml | 2 +-
src/interfaces/libpq/fe-protocol3.c | 21 +++++++++++++++++++++
2 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/doc/src/sgml/protocol.sgml b/doc/src/sgml/protocol.sgml
index cc5c8dc574c..2f2f3f9a6dc 100644
--- a/doc/src/sgml/protocol.sgml
+++ b/doc/src/sgml/protocol.sgml
@@ -4255,7 +4255,7 @@ psql "dbname=postgres replication=database" -c "IDENTIFY_SYSTEM;"
message, indicated by the length field.
</para>
<para>
- The maximum key length is 256 bytes. The
+ The minimum and maximum key length are 4 and 256 bytes, respectively. The
<productname>PostgreSQL</productname> server only sends keys up to
32 bytes, but the larger maximum size allows for future server
versions, as well as connection poolers and other middleware, to use
diff --git a/src/interfaces/libpq/fe-protocol3.c b/src/interfaces/libpq/fe-protocol3.c
index 0cca832c06a..223cd8fb51c 100644
--- a/src/interfaces/libpq/fe-protocol3.c
+++ b/src/interfaces/libpq/fe-protocol3.c
@@ -1569,6 +1569,27 @@ getBackendKeyData(PGconn *conn, int msgLength)
cancel_key_len = 5 + msgLength - (conn->inCursor - conn->inStart);
+ if (cancel_key_len != 4 && conn->pversion == PG_PROTOCOL(3, 0))
+ {
+ libpq_append_conn_error(conn, "received invalid BackendKeyData message: cancel key length %d is different from 4, which is not supported in version 3.0 of the protocol", cancel_key_len);
+ handleFatalError(conn);
+ return 0;
+ }
+
+ if (cancel_key_len < 4)
+ {
+ libpq_append_conn_error(conn, "received invalid BackendKeyData message: cancel key length %d is below minimum of 4 bytes", cancel_key_len);
+ handleFatalError(conn);
+ return 0;
+ }
+
+ if (cancel_key_len > 256)
+ {
+ libpq_append_conn_error(conn, "received invalid BackendKeyData message: cancel key length %d exceeds maximum of 256 bytes", cancel_key_len);
+ handleFatalError(conn);
+ return 0;
+ }
+
conn->be_cancel_key = malloc(cancel_key_len);
if (conn->be_cancel_key == NULL)
{
--
2.39.5