]> granicus.if.org Git - postgresql/commitdiff
Fix another ancient memory-leak bug in relcache.c.
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 24 Aug 2014 15:56:52 +0000 (11:56 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 24 Aug 2014 15:56:52 +0000 (11:56 -0400)
CheckConstraintFetch() leaked a cstring in the caller's context for each
CHECK constraint expression it copied into the relcache.  Ordinarily that
isn't problematic, but it can be during CLOBBER_CACHE testing because so
many reloads can happen during a single query; so complicate the code
slightly to allow freeing the cstring after use.  Per testing on buildfarm
member barnacle.

This is exactly like the leak fixed in AttrDefaultFetch() by commit
078b2ed291c758e7125d72c3a235f128d40a232b.  (Yes, this time I did look for
other instances of the same coding pattern :-(.)  Like that patch, no
back-patch, since it seems unlikely that there's any problem except under
very artificial test conditions.

BTW, it strikes me that both of these places would require further work
comparable to commit ab8c84db2f7af008151b848cf1d6a4672a39eecd, if we ever
supported defaults or check constraints on system catalogs: they both
assume they are copying into an empty relcache data structure, and that
conceivably wouldn't be the case during recursive reloading of a system
catalog.  This does not seem worth worrying about for the moment, since
there is no near-term prospect of supporting any such thing.  So I'll
just note the possibility for the archives' sake.

src/backend/utils/cache/relcache.c

index e4697f68aeb20c1790cc3081d461a928df9de58b..96bed96e75362e8c7ec458c6727004083bbb149e 100644 (file)
@@ -3552,8 +3552,6 @@ CheckConstraintFetch(Relation relation)
        SysScanDesc conscan;
        ScanKeyData skey[1];
        HeapTuple       htup;
-       Datum           val;
-       bool            isnull;
        int                     found = 0;
 
        ScanKeyInit(&skey[0],
@@ -3568,6 +3566,9 @@ CheckConstraintFetch(Relation relation)
        while (HeapTupleIsValid(htup = systable_getnext(conscan)))
        {
                Form_pg_constraint conform = (Form_pg_constraint) GETSTRUCT(htup);
+               Datum           val;
+               bool            isnull;
+               char       *s;
 
                /* We want check constraints only */
                if (conform->contype != CONSTRAINT_CHECK)
@@ -3590,8 +3591,11 @@ CheckConstraintFetch(Relation relation)
                        elog(ERROR, "null conbin for rel %s",
                                 RelationGetRelationName(relation));
 
-               check[found].ccbin = MemoryContextStrdup(CacheMemoryContext,
-                                                                                                TextDatumGetCString(val));
+               /* detoast and convert to cstring in caller's context */
+               s = TextDatumGetCString(val);
+               check[found].ccbin = MemoryContextStrdup(CacheMemoryContext, s);
+               pfree(s);
+
                found++;
        }