From: Amit Langote Date: Thu, 9 Apr 2026 05:45:31 +0000 (+0900) Subject: Add nkeys parameter to recheck_matched_pk_tuple() X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=e1cc57fabd6c32fcb740d62da90443f8c708951e;p=thirdparty%2Fpostgresql.git Add nkeys parameter to recheck_matched_pk_tuple() The function looped over ii_NumIndexKeyAttrs elements of the skeys array, but one caller (ri_FastPathFlushArray) passes a one-element array since it only handles single-column FKs. The function signature did not communicate this constraint, which static analysis flags as a potential out-of-bounds read. Add an nkeys parameter and assert that it matches ii_NumIndexKeyAttrs, then use it in the loop. The call sites already know the key count. Reported-by: Evan Montgomery-Recht Discussion: https://postgr.es/m/CAEg7pwcKf01FmDqFAf-Hzu_pYnMYScY_Otid-pe9uw3BJ6gq9g@mail.gmail.com --- diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c index 84f9fecdb4c..18ec858357d 100644 --- a/src/backend/utils/adt/ri_triggers.c +++ b/src/backend/utils/adt/ri_triggers.c @@ -329,7 +329,7 @@ static bool ri_LockPKTuple(Relation pk_rel, TupleTableSlot *slot, Snapshot snap, static bool ri_fastpath_is_applicable(const RI_ConstraintInfo *riinfo); static void ri_CheckPermissions(Relation query_rel); static bool recheck_matched_pk_tuple(Relation idxrel, ScanKeyData *skeys, - TupleTableSlot *new_slot); + int nkeys, TupleTableSlot *new_slot); static void build_index_scankeys(const RI_ConstraintInfo *riinfo, Relation idx_rel, Datum *pk_vals, char *pk_nulls, ScanKey skeys); @@ -3138,7 +3138,7 @@ ri_FastPathFlushArray(RI_FastPathEntry *fpentry, TupleTableSlot *fk_slot, idx_rel->rd_indcollation[0], fpmeta->regops[0], found_val); - if (!recheck_matched_pk_tuple(idx_rel, recheck_skey, pk_slot)) + if (!recheck_matched_pk_tuple(idx_rel, recheck_skey, 1, pk_slot)) continue; } @@ -3193,7 +3193,7 @@ ri_FastPathProbeOne(Relation pk_rel, Relation idx_rel, &concurrently_updated)) { if (concurrently_updated) - found = recheck_matched_pk_tuple(idx_rel, skey, slot); + found = recheck_matched_pk_tuple(idx_rel, skey, nkeys, slot); else found = true; } @@ -3340,7 +3340,7 @@ ri_CheckPermissions(Relation query_rel) * not found. */ static bool -recheck_matched_pk_tuple(Relation idxrel, ScanKeyData *skeys, +recheck_matched_pk_tuple(Relation idxrel, ScanKeyData *skeys, int nkeys, TupleTableSlot *new_slot) { /* @@ -3359,8 +3359,9 @@ recheck_matched_pk_tuple(Relation idxrel, ScanKeyData *skeys, indexInfo->ii_ExclusionOps == NULL); /* Form the index values and isnull flags given the table tuple. */ + Assert(nkeys == indexInfo->ii_NumIndexKeyAttrs); FormIndexDatum(indexInfo, new_slot, NULL, values, isnull); - for (int i = 0; i < indexInfo->ii_NumIndexKeyAttrs; i++) + for (int i = 0; i < nkeys; i++) { ScanKeyData *skey = &skeys[i];