[PATCH] Fix use-after-free of propgraph orphan static lists on xact abort

From: SATYANARAYANA NARLAPURAM <satyanarlapuram(at)gmail(dot)com>
To: PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>, Ashutosh Bapat <ashutosh(dot)bapat(dot)oss(at)gmail(dot)com>
Subject: [PATCH] Fix use-after-free of propgraph orphan static lists on xact abort
Date: 2026-05-12 17:52:52
Message-ID: CAHg+QDci9M0YQcmFbVbhcHifd0gUVL-n49RXXGwP8EBKj9trLQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hi hackers,

My PG19 fuzz tests detected the $subject issue in dependency.c.

Repro: It is not 100% deterministic because of the timeout, if hard to
follow can write
an injection point test.

\set ON_ERROR_STOP off

CREATE TABLE n1(id int PRIMARY KEY, name text);

-- Many indexes ensure the cascade takes enough time after the propgraph
-- element's deleteOneObject() for statement_timeout to fire.
DO $$ BEGIN
FOR i IN 1..50 LOOP
EXECUTE format('CREATE INDEX idx_%s ON n1 (id) WHERE id > %s', i, i);
END LOOP;
END $$;
CREATE PROPERTY GRAPH pg1 VERTEX TABLES (n1 LABEL l1 PROPERTIES(id, name));

CREATE TABLE n2(id int PRIMARY KEY, name text);
CREATE PROPERTY GRAPH pg2 VERTEX TABLES (n2 LABEL l2 PROPERTIES(id, name));

SET statement_timeout = '3ms';
DROP TABLE n1 CASCADE;
RESET statement_timeout;

DROP TABLE n2 CASCADE;

SELECT 1 AS status;

The static lists propgraph_orphan_label_graphids and
propgraph_orphan_property_graphids
in dependency.c are allocated in TopTransactionContext during
deleteOneObject(). They are
only reset on the success path of
performDeletion()/performMultipleDeletions(), in
run_deferred_propgraph_orphan_cleanup(). If a transaction aborts after the
lists have been
populated, for example due to statement_timeout, or any other error thrown
during the cascade),
AbortTransaction() frees TopTransactionContext but the static pointers
remain set. A subsequent
property graph cascade in the same backend session then passes the dangling
pointers to
list_append_unique_oid(), which walks freed memory. With assertions
enabled this trips

TRAP: failed Assert("IsOidList(list)"), File: "list.c", Line: 726

Without assertions this silently corrupts memory. Fix by resetting both
statics to NIL in the PG_FINALLY() blocks of
performDeletion() and performMultipleDeletions(), which execute on
both success and error paths.

Thanks,
Satya

Attachment Content-Type Size
0001-Fix-propgraph-orphan-static-list-use-after-free.patch application/octet-stream 2.5 KB

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Bruce Momjian 2026-05-12 19:11:16 Re: First draft of PG 19 release notes
Previous Message SATYANARAYANA NARLAPURAM 2026-05-12 17:41:53 Re: [Bug]Assertion failure in LATERAL GRAPH_TABLE with multi-label pattern