Release any detoasted copies of arrays that are made temporarily in
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 25 Jan 2008 04:46:07 +0000 (04:46 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 25 Jan 2008 04:46:07 +0000 (04:46 +0000)
ri_FetchConstraintInfo, to avoid a query-duration memory leak when that
routine is called by RI_FKey_keyequal_upd_fk (which isn't executed in a
short-lived context).  This problem was latent when the routine was added
in February, but it didn't become serious until the varvarlena patch made
it quite likely that the fields being examined would be "toasted" (ie, have
short headers).  Per report from Stephen Denne.

src/backend/utils/adt/ri_triggers.c

index 8559bac6961efb708ef0444b4bd2c9db972bade6..a75393d7d5219cfd153b3ce37404fa6d4ac6786a 100644 (file)
@@ -3099,6 +3099,8 @@ ri_FetchConstraintInfo(RI_ConstraintInfo *riinfo,
                elog(ERROR, "conkey is not a 1-D smallint array");
        riinfo->nkeys = numkeys;
        memcpy(riinfo->fk_attnums, ARR_DATA_PTR(arr), numkeys * sizeof(int16));
+       if ((Pointer) arr != DatumGetPointer(adatum))
+               pfree(arr);                             /* free de-toasted copy, if any */
 
        adatum = SysCacheGetAttr(CONSTROID, tup,
                                                         Anum_pg_constraint_confkey, &isNull);
@@ -3113,6 +3115,8 @@ ri_FetchConstraintInfo(RI_ConstraintInfo *riinfo,
                ARR_ELEMTYPE(arr) != INT2OID)
                elog(ERROR, "confkey is not a 1-D smallint array");
        memcpy(riinfo->pk_attnums, ARR_DATA_PTR(arr), numkeys * sizeof(int16));
+       if ((Pointer) arr != DatumGetPointer(adatum))
+               pfree(arr);                             /* free de-toasted copy, if any */
 
        adatum = SysCacheGetAttr(CONSTROID, tup,
                                                         Anum_pg_constraint_conpfeqop, &isNull);
@@ -3127,6 +3131,8 @@ ri_FetchConstraintInfo(RI_ConstraintInfo *riinfo,
                ARR_ELEMTYPE(arr) != OIDOID)
                elog(ERROR, "conpfeqop is not a 1-D Oid array");
        memcpy(riinfo->pf_eq_oprs, ARR_DATA_PTR(arr), numkeys * sizeof(Oid));
+       if ((Pointer) arr != DatumGetPointer(adatum))
+               pfree(arr);                             /* free de-toasted copy, if any */
 
        adatum = SysCacheGetAttr(CONSTROID, tup,
                                                         Anum_pg_constraint_conppeqop, &isNull);
@@ -3141,6 +3147,8 @@ ri_FetchConstraintInfo(RI_ConstraintInfo *riinfo,
                ARR_ELEMTYPE(arr) != OIDOID)
                elog(ERROR, "conppeqop is not a 1-D Oid array");
        memcpy(riinfo->pp_eq_oprs, ARR_DATA_PTR(arr), numkeys * sizeof(Oid));
+       if ((Pointer) arr != DatumGetPointer(adatum))
+               pfree(arr);                             /* free de-toasted copy, if any */
 
        adatum = SysCacheGetAttr(CONSTROID, tup,
                                                         Anum_pg_constraint_conffeqop, &isNull);
@@ -3155,6 +3163,8 @@ ri_FetchConstraintInfo(RI_ConstraintInfo *riinfo,
                ARR_ELEMTYPE(arr) != OIDOID)
                elog(ERROR, "conffeqop is not a 1-D Oid array");
        memcpy(riinfo->ff_eq_oprs, ARR_DATA_PTR(arr), numkeys * sizeof(Oid));
+       if ((Pointer) arr != DatumGetPointer(adatum))
+               pfree(arr);                             /* free de-toasted copy, if any */
 
        ReleaseSysCache(tup);
 }