From d139e479cd3b67127d49842b9e6ff51ade0d9265 Mon Sep 17 00:00:00 2001 From: kenny Date: Wed, 15 Jul 2026 00:12:16 +0800 Subject: [PATCH v1] Avoid crash on malformed CREATE_REPLICATION_SLOT reply libpqrcv_create_slot() checked only that the server's reply had status PGRES_TUPLES_OK before reading the consistent-point LSN (field 1) and the snapshot name (field 2) from the first returned row. A server that replies with a well-formed but empty result set (zero rows) therefore made PQgetvalue(res, 0, 1) return NULL, which is passed to pg_lsn_in() and dereferenced by strspn(), crashing the logical-replication tablesync worker with a segmentation fault. Validate the result shape before reading those fields, raising a protocol-violation error instead, matching what libpqrcv_identify_system() and the other result-consuming paths in this file already do. Reported-by: Yuelin Wang Discussion: https://postgr.es/m/19547-f7986f668f71e788@postgresql.org --- .../replication/libpqwalreceiver/libpqwalreceiver.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c index 5376519fea5..d1b3309e5bc 100644 --- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c +++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c @@ -1000,6 +1000,19 @@ libpqrcv_create_slot(WalReceiverConn *conn, const char *slotname, errmsg("could not create replication slot \"%s\": %s", slotname, pchomp(PQerrorMessage(conn->streamConn))))); + /* + * CREATE_REPLICATION_SLOT returns a single row with the slot name, the + * consistent point and the snapshot name; the latter two are read below. + * Verify the result shape so that a malformed reply lacking the expected + * row cannot lead to a NULL-pointer dereference. + */ + if (PQnfields(res) < 3 || PQntuples(res) != 1) + ereport(ERROR, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("invalid response from primary server"), + errdetail("Could not create replication slot \"%s\": got %d rows and %d fields, expected %d rows and %d or more fields.", + slotname, PQntuples(res), PQnfields(res), 1, 3))); + if (lsn) *lsn = DatumGetLSN(DirectFunctionCall1Coll(pg_lsn_in, InvalidOid, CStringGetDatum(PQgetvalue(res, 0, 1)))); -- 2.50.1 (Apple Git-155)