BUG #19484: Segmentation fault triggered by FDW

Started by PG Bug reporting form7 days ago4 messagesbugs
Jump to latest
#1PG Bug reporting form
noreply@postgresql.org

The following bug has been logged on the website:

Bug reference: 19484
Logged by: Chi Zhang
Email address: 798604270@qq.com
PostgreSQL version: 18.4
Operating system: Ubuntu 24.04
Description:

Hi,

I found the following test case triggers a segmentation fault:

```
\set ON_ERROR_STOP on

CREATE EXTENSION postgres_fdw;

CREATE SERVER loopback FOREIGN DATA WRAPPER postgres_fdw
OPTIONS (
host '/path/to/pg_socket',
port '5432',
dbname :'dbname'
);

CREATE USER MAPPING FOR postgres SERVER loopback
OPTIONS (user 'postgres');

CREATE SCHEMA r;
CREATE TABLE r.remote_p2 (a int NOT NULL, b int);

CREATE TABLE pt (a int NOT NULL, b int) PARTITION BY LIST (a);
CREATE TABLE pt_p1 PARTITION OF pt FOR VALUES IN (1);
CREATE FOREIGN TABLE pt_p2 PARTITION OF pt FOR VALUES IN (2)
SERVER loopback
OPTIONS (schema_name 'r', table_name 'remote_p2');

INSERT INTO pt_p1 VALUES (1, 10);
INSERT INTO r.remote_p2 VALUES (2, 20);

SET plan_cache_mode = force_generic_plan;

PREPARE upd(int) AS
UPDATE pt
SET b = b + 1
WHERE a = $1
RETURNING tableoid::regclass, a, b;

EXPLAIN (costs off) EXECUTE upd(2);
EXECUTE upd(2);
SELECT * FROM r.remote_p2 ORDER BY a;

```

This is the log:

```
2026-05-18 13:40:41.888 CST [21729] LOG: database system is ready to accept
connections
2026-05-18 13:41:03.317 CST [21932] LOG: unexpected EOF on client
connection with an open transaction
2026-05-18 13:41:03.317 CST [21729] LOG: client backend (PID 21931) was
terminated by signal 11: Segmentation fault
2026-05-18 13:41:03.317 CST [21729] DETAIL: Failed process was running:
EXECUTE upd(2);
2026-05-18 13:41:03.317 CST [21729] LOG: terminating any other active
server processes
2026-05-18 13:41:03.319 CST [21729] LOG: all server processes terminated;
reinitializing
2026-05-18 13:41:03.345 CST [21936] LOG: database system was interrupted;
last known up at 2026-05-18 13:40:41 CST
2026-05-18 13:41:03.509 CST [21936] LOG: database system was not properly
shut down; automatic recovery in progress
2026-05-18 13:41:03.513 CST [21936] LOG: redo starts at 0/98371040
2026-05-18 13:41:03.531 CST [21936] LOG: invalid record length at
0/987B6E68: expected at least 24, got 0
2026-05-18 13:41:03.531 CST [21936] LOG: redo done at 0/987B6E40 system
usage: CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.01 s
2026-05-18 13:41:03.537 CST [21937] LOG: checkpoint starting:
end-of-recovery fast wait
2026-05-18 13:41:03.654 CST [21937] LOG: checkpoint complete:
end-of-recovery fast wait: wrote 975 buffers (6.0%), wrote 3 SLRU buffers; 0
WAL file(s) added, 0 removed, 0
recycled; write=0.081 s, sync=0.030 s, total=0.121 s; sync files=325,
longest=0.005 s, average=0.001 s; distance=4375 kB, estimate=4375 kB;
lsn=0/987B6E68, redo lsn=0/987B6E68
2026-05-18 13:41:03.660 CST [21729] LOG: database system is ready to
accept connections
```

I built the Postgres from source code
901ed9b352b41f034e17bc540725082a488fce31 of github commit.

#2Ayush Tiwari
ayushtiwari.slg01@gmail.com
In reply to: PG Bug reporting form (#1)
Re: BUG #19484: Segmentation fault triggered by FDW

Hi,

On Wed, 20 May 2026 at 03:59, PG Bug reporting form <noreply@postgresql.org>
wrote:

The following bug has been logged on the website:

Bug reference: 19484
Logged by: Chi Zhang
Email address: 798604270@qq.com
PostgreSQL version: 18.4
Operating system: Ubuntu 24.04
Description:

Hi,

I found the following test case triggers a segmentation fault:

```
\set ON_ERROR_STOP on

CREATE EXTENSION postgres_fdw;

CREATE SERVER loopback FOREIGN DATA WRAPPER postgres_fdw
OPTIONS (
host '/path/to/pg_socket',
port '5432',
dbname :'dbname'
);

CREATE USER MAPPING FOR postgres SERVER loopback
OPTIONS (user 'postgres');

CREATE SCHEMA r;
CREATE TABLE r.remote_p2 (a int NOT NULL, b int);

CREATE TABLE pt (a int NOT NULL, b int) PARTITION BY LIST (a);
CREATE TABLE pt_p1 PARTITION OF pt FOR VALUES IN (1);
CREATE FOREIGN TABLE pt_p2 PARTITION OF pt FOR VALUES IN (2)
SERVER loopback
OPTIONS (schema_name 'r', table_name 'remote_p2');

INSERT INTO pt_p1 VALUES (1, 10);
INSERT INTO r.remote_p2 VALUES (2, 20);

SET plan_cache_mode = force_generic_plan;

PREPARE upd(int) AS
UPDATE pt
SET b = b + 1
WHERE a = $1
RETURNING tableoid::regclass, a, b;

EXPLAIN (costs off) EXECUTE upd(2);
EXECUTE upd(2);
SELECT * FROM r.remote_p2 ORDER BY a;

Thanks for the very precise repro, that made this easy to track down.

I reproduced the crash on master. The plan EXPLAIN under
force_generic_plan shows runtime pruning is in effect:

Update on pt
Foreign Update on pt_p2 pt_2
-> Append
Subplans Removed: 1
-> Foreign Update on pt_p2 pt_2

The SEGV happens inside postgresBeginForeignModify() because
ExecInitModifyTable() builds re-indexed "kept" copies of several
parallel per-result-relation lists after dropping pruned relations -
withCheckOptionLists, returningLists, updateColnosLists,
mergeActionLists and mergeJoinConditions, however two members were
missed:

- node->fdwPrivLists, read with list_nth(node->fdwPrivLists, i) when
BeginForeignModify() is called, and
- node->fdwDirectModifyPlans, checked with bms_is_member(i, ...) when
setting ri_usesFdwDirectModify.

Both were still indexed against the original (pre-pruning) positions
while the surrounding loop's "i" is now the kept position. When the
foreign partition's kept-index no longer matched its original index,
BeginForeignModify() got the wrong fdw_private and crashed.

Attached patch builds re-indexed kept copies for these two arrays in
the same loop as the other parallel lists, and uses them at the two
call sites.

Regards,
Ayush

Attachments:

v1-0001-Re-index-ModifyTable-FDW-arrays-when-pruning-resu.patchapplication/octet-stream; name=v1-0001-Re-index-ModifyTable-FDW-arrays-when-pruning-resu.patchDownload+64-3
#3Etsuro Fujita
fujita.etsuro@lab.ntt.co.jp
In reply to: Ayush Tiwari (#2)
Re: BUG #19484: Segmentation fault triggered by FDW

Hi,

On Wed, May 20, 2026 at 5:37 AM Ayush Tiwari
<ayushtiwari.slg01@gmail.com> wrote:

On Wed, 20 May 2026 at 03:59, PG Bug reporting form <noreply@postgresql.org> wrote:

I found the following test case triggers a segmentation fault:

[snip]

Thanks for the very precise repro, that made this easy to track down.

I reproduced the crash on master. The plan EXPLAIN under
force_generic_plan shows runtime pruning is in effect:

Update on pt
Foreign Update on pt_p2 pt_2
-> Append
Subplans Removed: 1
-> Foreign Update on pt_p2 pt_2

The SEGV happens inside postgresBeginForeignModify() because
ExecInitModifyTable() builds re-indexed "kept" copies of several
parallel per-result-relation lists after dropping pruned relations -
withCheckOptionLists, returningLists, updateColnosLists,
mergeActionLists and mergeJoinConditions, however two members were
missed:

- node->fdwPrivLists, read with list_nth(node->fdwPrivLists, i) when
BeginForeignModify() is called, and
- node->fdwDirectModifyPlans, checked with bms_is_member(i, ...) when
setting ri_usesFdwDirectModify.

Both were still indexed against the original (pre-pruning) positions
while the surrounding loop's "i" is now the kept position. When the
foreign partition's kept-index no longer matched its original index,
BeginForeignModify() got the wrong fdw_private and crashed.

Attached patch builds re-indexed kept copies for these two arrays in
the same loop as the other parallel lists, and uses them at the two
call sites.

Thanks Chi for the report, and Ayush for the analysis and patch! Will review.

Best regards,
Etsuro Fujita

#4Matheus Alcantara
matheusssilv97@gmail.com
In reply to: Ayush Tiwari (#2)
Re: BUG #19484: Segmentation fault triggered by FDW

On Wed May 20, 2026 at 9:37 AM -03, Ayush Tiwari wrote:

I reproduced the crash on master. The plan EXPLAIN under
force_generic_plan shows runtime pruning is in effect:

Update on pt
Foreign Update on pt_p2 pt_2
-> Append
Subplans Removed: 1
-> Foreign Update on pt_p2 pt_2

The SEGV happens inside postgresBeginForeignModify() because
ExecInitModifyTable() builds re-indexed "kept" copies of several
parallel per-result-relation lists after dropping pruned relations -
withCheckOptionLists, returningLists, updateColnosLists,
mergeActionLists and mergeJoinConditions, however two members were
missed:

- node->fdwPrivLists, read with list_nth(node->fdwPrivLists, i) when
BeginForeignModify() is called, and
- node->fdwDirectModifyPlans, checked with bms_is_member(i, ...) when
setting ri_usesFdwDirectModify.

Both were still indexed against the original (pre-pruning) positions
while the surrounding loop's "i" is now the kept position. When the
foreign partition's kept-index no longer matched its original index,
BeginForeignModify() got the wrong fdw_private and crashed.

Attached patch builds re-indexed kept copies for these two arrays in
the same loop as the other parallel lists, and uses them at the two
call sites.

Hi, thanks for the patch. This issue started on version 18 by commit
cbc127917e0.

The patch fixes the issue and it make sense to me. One a minor comment
is that I think pg_indent is needed on nodeModifyTable.c

--
Matheus Alcantara
EDB: https://www.enterprisedb.com