mirror of
https://github.com/postgres/postgres.git
synced 2026-10-23 13:29:09 +03:00
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/CA+HiwqFaipkMsZ8XP-9sMk21h0Q7rih=NpJQXsBAaD39VtnrOA@mail.gmail.com
This commit is contained in:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user