v1-0001-Add-nkeys-parameter-to-recheck_matched_pk_tuple.patch
application/octet-stream
Filename: v1-0001-Add-nkeys-parameter-to-recheck_matched_pk_tuple.patch
Type: application/octet-stream
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v1-0001
Subject: Add nkeys parameter to recheck_matched_pk_tuple()
| File | + | − |
|---|---|---|
| src/backend/utils/adt/ri_triggers.c | 6 | 5 |
From 344ba694451fbaa57bbb2e12930fe20fd425e806 Mon Sep 17 00:00:00 2001
From: Amit Langote <amitlan@postgresql.org>
Date: Wed, 8 Apr 2026 10:20:15 +0900
Subject: [PATCH v1] 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 <montge@mianetworks.net>
Discussion: https://postgr.es/m/CAEg7pwcKf01FmDqFAf-Hzu_pYnMYScY_Otid-pe9uw3BJ6gq9g@mail.gmail.com
---
src/backend/utils/adt/ri_triggers.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
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];
--
2.47.3