]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Add nkeys parameter to recheck_matched_pk_tuple()
authorAmit Langote <amitlan@postgresql.org>
Thu, 9 Apr 2026 05:45:31 +0000 (14:45 +0900)
committerAmit Langote <amitlan@postgresql.org>
Thu, 9 Apr 2026 05:45:31 +0000 (14:45 +0900)
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 <montge@mianetworks.net>
Discussion: https://postgr.es/m/CAEg7pwcKf01FmDqFAf-Hzu_pYnMYScY_Otid-pe9uw3BJ6gq9g@mail.gmail.com

src/backend/utils/adt/ri_triggers.c

index 84f9fecdb4c8837c1b29052779799f3c6d9337dd..18ec858357dd40d8d7564d3bb889baa59a279b87 100644 (file)
@@ -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];