Skip to content

Commit 49c3000

Browse files
committed
Fix (some of) pltcl memory usage
As reported by Bill Parker, PL/Tcl did not validate some malloc() calls against NULL return. Fix by using palloc() in a new long-lived memory context instead. This allows us to simplify error handling too, by simply deleting the memory context instead of doing retail frees. There's still a lot that could be done to improve PL/Tcl's memory handling ... This is pretty ancient, so backpatch all the way back. Author: Michael Paquier and Álvaro Herrera Discussion: https://www.postgresql.org/message-id/CAFrbyQwyLDYXfBOhPfoBGqnvuZO_Y90YgqFM11T2jvnxjLFmqw@mail.gmail.com
1 parent 29efe1b commit 49c3000

File tree

1 file changed

+18
-9
lines changed

1 file changed

+18
-9
lines changed

src/pl/tcl/pltcl.c

+18-9
Original file line numberDiff line numberDiff line change
@@ -2106,6 +2106,7 @@ static int
21062106
pltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp,
21072107
int argc, CONST84 char *argv[])
21082108
{
2109+
volatile MemoryContext plan_cxt = NULL;
21092110
int nargs;
21102111
CONST84 char **args;
21112112
pltcl_query_desc *qdesc;
@@ -2134,13 +2135,24 @@ pltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp,
21342135

21352136
/************************************************************
21362137
* Allocate the new querydesc structure
2138+
*
2139+
* struct qdesc and subsidiary data all live in plan_cxt. Note that if the
2140+
* function is recompiled for whatever reason, permanent memory leaks
2141+
* occur. FIXME someday.
21372142
************************************************************/
2138-
qdesc = (pltcl_query_desc *) malloc(sizeof(pltcl_query_desc));
2143+
plan_cxt = AllocSetContextCreate(TopMemoryContext,
2144+
"PL/TCL spi_prepare query",
2145+
ALLOCSET_SMALL_MINSIZE,
2146+
ALLOCSET_SMALL_INITSIZE,
2147+
ALLOCSET_SMALL_MAXSIZE);
2148+
MemoryContextSwitchTo(plan_cxt);
2149+
qdesc = (pltcl_query_desc *) palloc0(sizeof(pltcl_query_desc));
21392150
snprintf(qdesc->qname, sizeof(qdesc->qname), "%p", qdesc);
21402151
qdesc->nargs = nargs;
2141-
qdesc->argtypes = (Oid *) malloc(nargs * sizeof(Oid));
2142-
qdesc->arginfuncs = (FmgrInfo *) malloc(nargs * sizeof(FmgrInfo));
2143-
qdesc->argtypioparams = (Oid *) malloc(nargs * sizeof(Oid));
2152+
qdesc->argtypes = (Oid *) palloc(nargs * sizeof(Oid));
2153+
qdesc->arginfuncs = (FmgrInfo *) palloc(nargs * sizeof(FmgrInfo));
2154+
qdesc->argtypioparams = (Oid *) palloc(nargs * sizeof(Oid));
2155+
MemoryContextSwitchTo(oldcontext);
21442156

21452157
/************************************************************
21462158
* Execute the prepare inside a sub-transaction, so we can cope with
@@ -2168,7 +2180,7 @@ pltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp,
21682180
getTypeInputInfo(typId, &typInput, &typIOParam);
21692181

21702182
qdesc->argtypes[i] = typId;
2171-
perm_fmgr_info(typInput, &(qdesc->arginfuncs[i]));
2183+
fmgr_info_cxt(typInput, &(qdesc->arginfuncs[i]), plan_cxt);
21722184
qdesc->argtypioparams[i] = typIOParam;
21732185
}
21742186

@@ -2195,10 +2207,7 @@ pltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp,
21952207
{
21962208
pltcl_subtrans_abort(interp, oldcontext, oldowner);
21972209

2198-
free(qdesc->argtypes);
2199-
free(qdesc->arginfuncs);
2200-
free(qdesc->argtypioparams);
2201-
free(qdesc);
2210+
MemoryContextDelete(plan_cxt);
22022211
ckfree((char *) args);
22032212

22042213
return TCL_ERROR;

0 commit comments

Comments
 (0)