Re: BUG #19484: Segmentation fault triggered by FDW

Ayush Tiwari <ayushtiwari.slg01@gmail.com>

From: Ayush Tiwari <ayushtiwari.slg01@gmail.com>
To: 798604270@qq.com, pgsql-bugs@lists.postgresql.org, Etsuro Fujita <etsuro.fujita@gmail.com>
Date: 2026-05-20T12:37:16Z
Lists: pgsql-bugs

Attachments

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

Commits

Same data as JSON: GET /api/v1/messages/:b64id/commits the thread's linked commits as JSON, with link sources. API reference →
  1. Avoid ABI break in ModifyTableState from the FDW pruning fix

  2. Re-index ModifyTable FDW arrays when pruning result relations

  3. Fix universal builds on MacOS

  4. Track unpruned relids to avoid processing pruned relations