CheckNNConstraintFetch: Fill all of ConstrCheck in a single pass
authorÁlvaro Herrera <alvherre@kurilemu.de>
Wed, 29 Oct 2025 10:41:39 +0000 (11:41 +0100)
committerÁlvaro Herrera <alvherre@kurilemu.de>
Wed, 29 Oct 2025 10:41:39 +0000 (11:41 +0100)
Previously, we'd fill all fields except ccbin, and only later obtain and
detoast ccbin, with hypothetical failures being possible.  If ccbin is
null (rare catalog corruption I have never witnessed) or its a corrupted
toast entry, we leak a tiny bit of memory in CacheMemoryContext from
having strdup'd the constraint name.  Repair these by only attempting to
fill the struct once ccbin has been detoasted.

Author: Ranier Vilela <ranier.vf@gmail.com>
Discussion: https://postgr.es/m/CAEudQAr=i3_Z4GvmediX900+sSySTeMkvuytYShhQqEwoGyvhA@mail.gmail.com

src/backend/utils/cache/relcache.c

index 2b798b823ea5dc004897920666d8fab983f51548..915d0bc908423c6fc6a89f5f3fe7d49d9c826a8e 100644 (file)
@@ -4658,12 +4658,6 @@ CheckNNConstraintFetch(Relation relation)
                        break;
                }
 
-               check[found].ccenforced = conform->conenforced;
-               check[found].ccvalid = conform->convalidated;
-               check[found].ccnoinherit = conform->connoinherit;
-               check[found].ccname = MemoryContextStrdup(CacheMemoryContext,
-                                                                                                 NameStr(conform->conname));
-
                /* Grab and test conbin is actually set */
                val = fastgetattr(htup,
                                                  Anum_pg_constraint_conbin,
@@ -4676,7 +4670,13 @@ CheckNNConstraintFetch(Relation relation)
                        /* detoast and convert to cstring in caller's context */
                        char       *s = TextDatumGetCString(val);
 
+                       check[found].ccenforced = conform->conenforced;
+                       check[found].ccvalid = conform->convalidated;
+                       check[found].ccnoinherit = conform->connoinherit;
+                       check[found].ccname = MemoryContextStrdup(CacheMemoryContext,
+                                                                                                         NameStr(conform->conname));
                        check[found].ccbin = MemoryContextStrdup(CacheMemoryContext, s);
+
                        pfree(s);
                        found++;
                }