| From: | Zhijie Hou <houzhijie22(at)gmail(dot)com> |
|---|---|
| To: | brar(at)gmx(dot)de, pgsql-bugs(at)lists(dot)postgresql(dot)org |
| Subject: | Re: BUG #19795: pgoutput: walsender crashes on START_REPLICATION option without a value |
| Date: | 2026-10-25 15:31:52 |
| Message-ID: | CAFvd2n-BDb2rp+8jKyUrf-Uv4YgZqDa+O0gzt_JDfCpC-9gGxA@mail.gmail.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-bugs |
Hi,
On Sun, Oct 25, 2026 at 9:31 PM PG Bug reporting form
<noreply(at)postgresql(dot)org> wrote:
>
> The following bug has been logged on the website:
>
> Bug reference: 19795
> Logged by: Brar Piening
> Email address: brar(at)gmx(dot)de
> PostgreSQL version: 18.6
> Operating system: Windows 11 x64 (EDB installer builds)
> Description:
>
> A START_REPLICATION option without a value crashes the walsender when the
> output plugin is pgoutput and the option is proto_version or
> publication_names.
> The postmaster then restarts all sessions.
> A role with REPLICATION is enough; it doesn't need to be a superuser.
>
> Steps, on a fresh cluster with wal_level = logical:
>
> -- as a superuser
> CREATE PUBLICATION pub FOR ALL TABLES;
> SELECT pg_create_logical_replication_slot('s', 'pgoutput');
> CREATE ROLE repuser LOGIN REPLICATION;
>
> pg_recvlogical -d postgres -U repuser --slot=s --start -o proto_version \
> -f - --no-loop
>
> (Without --no-loop, pg_recvlogical sends the command again after a few
> seconds.)
>
> pg_recvlogical sends START_REPLICATION SLOT "s" LOGICAL 0/0
> ("proto_version")
> and reports:
>
> pg_recvlogical: error: could not send replication command
> "START_REPLICATION SLOT "s" LOGICAL 0/0 ("proto_version")": server closed
> the connection unexpectedly
>
> Server log (18.6):
>
> LOG: client backend (PID 21132) was terminated by exception 0xC0000005
> DETAIL: Failed process was running: START_REPLICATION SLOT "s" LOGICAL
> 0/0 ("proto_version")
> LOG: terminating any other active server processes
> LOG: all server processes terminated; reinitializing
> LOG: database system was not properly shut down; automatic recovery in
> progress
> ...
> LOG: database system is ready to accept connections
>
> "-o publication_names" crashes the same way. I reproduced both on 14.24,
> 15.19, 16.15, 17.11 and 18.6, all Windows builds, where the crash shows up
> as an access violation.
>
> Expected: an error, as for pgoutput's origin option without a value:
>
> ERROR: origin requires a parameter
> CONTEXT: slot "s", output plugin "pgoutput", in the startup callback
>
> Cause: the replication grammar accepts an option without a value and leaves
> DefElem.arg NULL (repl_gram.y, plugin_opt_arg: "| /* EMPTY */ { $$ = NULL;
> }").
> parse_output_parameters() in pgoutput.c allows this ("Assert(defel->arg ==
> NULL || IsA(defel->arg, String))"), but for proto_version and
> publication_names it calls strVal(defel->arg), which dereferences the NULL
> pointer.
> The other options are read with defGetBoolean() (a missing value means true)
> or defGetString() (origin, which raises the error above).
> The SQL functions such as pg_logical_slot_get_changes() can't produce a NULL
> arg, since logicalfuncs.c wraps every value in makeString().
> So only the replication protocol path crashes.
> test_decoding checks for a NULL arg itself.
>
> Suggested fix: read both options with defGetString(defel), as origin does,
> on all supported branches.
>
> I found this while working on Npgsql (the .NET driver), whose generic
> logical replication API currently sends an option without a value when the
> caller passes null.
Thanks for the report and analysis. I could reproduce the crash, and I
agree with the suggested fix.
Attached is a patch that uses defGetString() for "proto_version" and
"publication_names" and adds a simple test in 030_pg_recvlogical.pl
to confirm it works.
Best Regards,
Zhijie Hou
| Attachment | Content-Type | Size |
|---|---|---|
| v1-0001-Fix-pgoutput-crash-on-missing-option-values.patch | application/x-patch | 3.1 KB |
| From | Date | Subject | |
|---|---|---|---|
| Next Message | shihao zhong | 2026-10-25 16:04:37 | Re: first_value()/nth_value() with IGNORE NULLS loop forever (EXCLUDE GROUP/TIES, frame past partition end, no ORDER BY) |
| Previous Message | shihao zhong | 2026-10-25 15:05:28 | Re: BUG #19794: Assert in btvacuumcleanup() fails when page counted in pages_free twice |