From de709fdf8e4d957b73c4cdcb23ae4c7bf6e879e8 Mon Sep 17 00:00:00 2001 From: Amit Langote Date: Mon, 5 Oct 2026 08:24:06 +0900 Subject: [PATCH v1] Fix possible crash when RI fast-path metadata is invalidated mid-check ri_FastPathCheck() read riinfo->fpmeta again after ri_CheckFunctionPermissions(), which looks up catalog entries and so can process invalidation messages. If one of them reaches InvalidateConstraintCacheCallBack() for the constraint, as a pg_amop change or a cache reset would, the callback detaches the metadata and sets riinfo->fpmeta to NULL, which build_index_scankeys() then dereferences. The callback already defers freeing detached metadata until AtEOXact_RI(), and its comment assumes callers keep their own pointer to it, so use a local pointer instead of riinfo->fpmeta. There is no test, as hitting this needs an invalidation to arrive during those catalog lookups. Discussion: https://postgr.es/m/ --- src/backend/utils/adt/ri_triggers.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c index 0bcb0f9b3cf..56ca5c648e7 100644 --- a/src/backend/utils/adt/ri_triggers.c +++ b/src/backend/utils/adt/ri_triggers.c @@ -2783,6 +2783,7 @@ ri_FastPathCheck(RI_ConstraintInfo *riinfo, Oid saved_userid; int saved_sec_context; Snapshot snapshot; + FastPathMeta *fpmeta; INJECTION_POINT("ri-before-pk-lock", NULL); @@ -2854,11 +2855,19 @@ ri_FastPathCheck(RI_ConstraintInfo *riinfo, riinfo = ri_LoadConstraintInfo(riinfo->constraint_id); ri_populate_fastpath_metadata(riinfo, fk_rel, idx_rel); } - Assert(riinfo->fpmeta); - ri_CheckFunctionPermissions(riinfo, riinfo->fpmeta); + + /* + * Use our own pointer to the metadata from here on. The permission + * checks below look up catalog entries and so can process invalidation + * messages, which detach riinfo->fpmeta (see + * InvalidateConstraintCacheCallBack()); the detached object stays valid + * until AtEOXact_RI(). + */ + fpmeta = riinfo->fpmeta; + Assert(fpmeta); + ri_CheckFunctionPermissions(riinfo, fpmeta); ri_ExtractValues(fk_rel, newslot, riinfo, false, pk_vals, pk_nulls); - build_index_scankeys(riinfo, riinfo->fpmeta, idx_rel, pk_vals, pk_nulls, - skey); + build_index_scankeys(riinfo, fpmeta, idx_rel, pk_vals, pk_nulls, skey); found = ri_FastPathProbeOne(pk_rel, idx_rel, scandesc, slot, snapshot, riinfo, skey, riinfo->nkeys); SetUserIdAndSecContext(saved_userid, saved_sec_context); -- 2.47.3