Re: BUG #19547: libpqrcv_create_slot dereferences NULL on a malformed CREATE_REPLICATION_SLOT reply
Hi,
Thanks for the detailed report and analysis. Here is a patch.
libpqrcv_create_slot() only checked PGRES_TUPLES_OK before reading the
consistent-point LSN and snapshot name from the first row, so a reply with
zero rows made PQgetvalue(res, 0, 1) return NULL, which pg_lsn_in() then
dereferenced -> crash in the tablesync worker.
The patch validates the result shape (>= 3 fields, exactly 1 row) before
reading those fields and raises a protocol-violation error otherwise,
mirroring what libpqrcv_identify_system() and the other result-consuming
paths in this file already do. I used "< 3" rather than "< 4" because the
function only reads fields 1 and 2.
Builds cleanly and "meson test --suite subscription" passes. I could not
find a good way to add a regression test, since it needs a rogue server
that returns a malformed reply; suggestions welcome.
Regards,
Kenny
Attachments:
v1-0001-Avoid-crash-on-malformed-CREATE_REPLICATION_SLOT-.patchapplication/octet-stream; name=v1-0001-Avoid-crash-on-malformed-CREATE_REPLICATION_SLOT-.patchDownload+13-1
Hi Kenny,
The patch validates the result shape (>= 3 fields, exactly 1 row) before
reading those fields and raises a protocol-violation error otherwise,
mirroring what libpqrcv_identify_system() and the other result-consuming
paths in this file already do. I used "< 3" rather than "< 4" because the
function only reads fields 1 and 2.
Hmm, but IDENTIFY_SYSTEM requires that number returned attributes should be 3 or
4, nevertheless first and second columns are checked. If we follow, isn't it
better to require that there are 4 attributes? I checked old versions and the
command has returned 4 attributes from the beginning [1]https://github.com/postgres/postgres/blob/b1b8b8e6f141e378db21c609d8ee74d9125a4aca/src/backend/replication/walsender.c#L853.
Best regards,
Hayato Kuroda
FUJITSU LIMITED
Hi Hayato,
Thanks for looking at this.
Hmm, but IDENTIFY_SYSTEM requires that number returned attributes should be 3 or
4, nevertheless first and second columns are checked. If we follow, isn't it
better to require that there are 4 attributes? I checked old versions and the
command has returned 4 attributes from the beginning [1].
Agreed. IDENTIFY_SYSTEM tolerates 3 columns only because older servers (9.3
and earlier) actually returned 3, whereas CREATE_REPLICATION_SLOT has always
returned 4, so there is no reason to be lenient here. v2 attached requires 4
fields, and updates the comment and errdetail accordingly.
Best regards,
Kenny Chen
Hayato Kuroda (Fujitsu) <kuroda.hayato@fujitsu.com> 於 2026年7月15日週三 下午12:33寫道:
Show quoted text
Hi Kenny,
The patch validates the result shape (>= 3 fields, exactly 1 row) before
reading those fields and raises a protocol-violation error otherwise,
mirroring what libpqrcv_identify_system() and the other result-consuming
paths in this file already do. I used "< 3" rather than "< 4" because the
function only reads fields 1 and 2.Hmm, but IDENTIFY_SYSTEM requires that number returned attributes should be 3 or
4, nevertheless first and second columns are checked. If we follow, isn't it
better to require that there are 4 attributes? I checked old versions and the
command has returned 4 attributes from the beginning [1].Best regards,
Hayato Kuroda
FUJITSU LIMITED
Attachments:
v2-0001-Avoid-crash-on-malformed-CREATE_REPLICATION_SLOT-.patchapplication/octet-stream; name=v2-0001-Avoid-crash-on-malformed-CREATE_REPLICATION_SLOT-.patchDownload+13-1
On Wed, Jul 15, 2026 at 8:51 PM Kenny Chen <kennychen851228@gmail.com> wrote:
Agreed. IDENTIFY_SYSTEM tolerates 3 columns only because older servers (9.3
and earlier) actually returned 3, whereas CREATE_REPLICATION_SLOT has always
returned 4, so there is no reason to be lenient here. v2 attached requires 4
fields, and updates the comment and errdetail accordingly.
Agreed. So,
+ if (PQnfields(res) < 4 || 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, 4)));
"PQnfields(res) < 4" should be "PQnfields(res) != 4"?
If so, "or more" in the detail message should be removed as well.
Regards,
--
Fujii Masao
Hi Fujii,
"PQnfields(res) < 4" should be "PQnfields(res) != 4"?
If so, "or more" in the detail message should be removed as well.
Right, CREATE_REPLICATION_SLOT always returns exactly 4 columns, so != 4 is
more accurate. v3 attached uses != 4 and drops "or more" from the errdetail.
Regards,
Kenny
Fujii Masao <masao.fujii@gmail.com> 於 2026年7月15日週三 下午10:10寫道:
Show quoted text
On Wed, Jul 15, 2026 at 8:51 PM Kenny Chen <kennychen851228@gmail.com> wrote:
Agreed. IDENTIFY_SYSTEM tolerates 3 columns only because older servers (9.3
and earlier) actually returned 3, whereas CREATE_REPLICATION_SLOT has always
returned 4, so there is no reason to be lenient here. v2 attached requires 4
fields, and updates the comment and errdetail accordingly.Agreed. So,
+ if (PQnfields(res) < 4 || 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, 4)));"PQnfields(res) < 4" should be "PQnfields(res) != 4"?
If so, "or more" in the detail message should be removed as well.Regards,
--
Fujii Masao
Attachments:
v3-0001-Avoid-crash-on-malformed-CREATE_REPLICATION_SLOT-.patchapplication/octet-stream; name=v3-0001-Avoid-crash-on-malformed-CREATE_REPLICATION_SLOT-.patchDownload+13-1
Dear Kenny,
Right, CREATE_REPLICATION_SLOT always returns exactly 4 columns, so != 4 is
more accurate. v3 attached uses != 4 and drops "or more" from the errdetail.
Basically LGTM. From my perspective the code comment might be too detail:
"CREATE_REPLICATION_SLOT has always returned a single row with four columns"
might be enough. But it's not the strong opinion - let's confirm the Fujii-san's idea.
Best regards,
Hayato Kuroda
FUJITSU LIMITED
On Thu, Jul 16, 2026 at 9:36 AM Hayato Kuroda (Fujitsu)
<kuroda.hayato@fujitsu.com> wrote:
Dear Kenny,
Right, CREATE_REPLICATION_SLOT always returns exactly 4 columns, so != 4 is
more accurate. v3 attached uses != 4 and drops "or more" from the errdetail.Basically LGTM. From my perspective the code comment might be too detail:
"CREATE_REPLICATION_SLOT has always returned a single row with four columns"
might be enough.
+1
So I've updated the comment to a simpler version and pushed the patch. Thanks!
Regards,
--
Fujii Masao