From 6ae651e19232ede52fe417001c8f8906984cafd6 Mon Sep 17 00:00:00 2001 From: Ayush Tiwari Date: Thu, 10 Sep 2026 19:02:10 +0530 Subject: [PATCH v1] Use pg_parse_lsn() for START_REPLICATION The replication command scanner parses LSNs with sscanf() into uint32 variables. This can silently change an LSN with an overlong component: the high component wraps around, while the low component is truncated to the first eight digits because of the field width in "%08X". Use pg_parse_lsn() instead. This enforces the same limit of one to eight hexadecimal digits per component as pg_lsn input and rejects invalid LSNs rather than starting replication at a different location. Test overlong high and low components in the existing logical decoding TAP test. --- src/backend/replication/repl_scanner.l | 6 ++---- src/test/recovery/t/006_logical_decoding.pl | 12 ++++++++++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/backend/replication/repl_scanner.l b/src/backend/replication/repl_scanner.l index 70b137acedc..af1615f9dbf 100644 --- a/src/backend/replication/repl_scanner.l +++ b/src/backend/replication/repl_scanner.l @@ -15,6 +15,7 @@ */ #include "postgres.h" +#include "common/pg_parse_lsn.h" #include "nodes/parsenodes.h" #include "utils/builtins.h" #include "parser/scansup.h" @@ -153,11 +154,8 @@ UPLOAD_MANIFEST { return K_UPLOAD_MANIFEST; } } {hexdigit}+\/{hexdigit}+ { - uint32 hi, - lo; - if (sscanf(yytext, "%X/%08X", &hi, &lo) != 2) + if (!pg_parse_lsn(yytext, &yylval->recptr)) replication_yyerror(NULL, yyscanner, "invalid streaming start location"); - yylval->recptr = ((uint64) hi) << 32 | lo; return RECPTR; } diff --git a/src/test/recovery/t/006_logical_decoding.pl b/src/test/recovery/t/006_logical_decoding.pl index 97d11f98b59..490e7a80c64 100644 --- a/src/test/recovery/t/006_logical_decoding.pl +++ b/src/test/recovery/t/006_logical_decoding.pl @@ -39,6 +39,18 @@ like( qr/replication slot "test_slot" was not created in this database/, "Logical decoding correctly fails to start"); +for my $lsn ('123456789/0', '0/123456789') +{ + ($result, $stdout, $stderr) = $node_primary->psql( + 'template1', + qq[START_REPLICATION $lsn], + replication => 'database'); + like( + $stderr, + qr/invalid streaming start location/, + "START_REPLICATION rejects overlong LSN $lsn"); +} + ($result, $stdout, $stderr) = $node_primary->psql( 'template1', qq[READ_REPLICATION_SLOT test_slot;], -- 2.34.1