Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit f8d67ca

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 8d90736 commit f8d67ca

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
@@ -2104,6 +2104,7 @@ static int
21042104
pltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp,
21052105
int argc, CONST84 char *argv[])
21062106
{
2107+
volatile MemoryContext plan_cxt = NULL;
21072108
int nargs;
21082109
CONST84 char **args;
21092110
pltcl_query_desc *qdesc;
@@ -2132,13 +2133,24 @@ pltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp,
21322133

21332134
/************************************************************
21342135
* Allocate the new querydesc structure
2136+
*
2137+
* struct qdesc and subsidiary data all live in plan_cxt. Note that if the
2138+
* function is recompiled for whatever reason, permanent memory leaks
2139+
* occur. FIXME someday.
21352140
************************************************************/
2136-
qdesc = (pltcl_query_desc *) malloc(sizeof(pltcl_query_desc));
2141+
plan_cxt = AllocSetContextCreate(TopMemoryContext,
2142+
"PL/TCL spi_prepare query",
2143+
ALLOCSET_SMALL_MINSIZE,
2144+
ALLOCSET_SMALL_INITSIZE,
2145+
ALLOCSET_SMALL_MAXSIZE);
2146+
MemoryContextSwitchTo(plan_cxt);
2147+
qdesc = (pltcl_query_desc *) palloc0(sizeof(pltcl_query_desc));
21372148
snprintf(qdesc->qname, sizeof(qdesc->qname), "%p", qdesc);
21382149
qdesc->nargs = nargs;
2139-
qdesc->argtypes = (Oid *) malloc(nargs * sizeof(Oid));
2140-
qdesc->arginfuncs = (FmgrInfo *) malloc(nargs * sizeof(FmgrInfo));
2141-
qdesc->argtypioparams = (Oid *) malloc(nargs * sizeof(Oid));
2150+
qdesc->argtypes = (Oid *) palloc(nargs * sizeof(Oid));
2151+
qdesc->arginfuncs = (FmgrInfo *) palloc(nargs * sizeof(FmgrInfo));
2152+
qdesc->argtypioparams = (Oid *) palloc(nargs * sizeof(Oid));
2153+
MemoryContextSwitchTo(oldcontext);
21422154

21432155
/************************************************************
21442156
* Execute the prepare inside a sub-transaction, so we can cope with
@@ -2166,7 +2178,7 @@ pltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp,
21662178
getTypeInputInfo(typId, &typInput, &typIOParam);
21672179

21682180
qdesc->argtypes[i] = typId;
2169-
perm_fmgr_info(typInput, &(qdesc->arginfuncs[i]));
2181+
fmgr_info_cxt(typInput, &(qdesc->arginfuncs[i]), plan_cxt);
21702182
qdesc->argtypioparams[i] = typIOParam;
21712183
}
21722184

@@ -2193,10 +2205,7 @@ pltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp,
21932205
{
21942206
pltcl_subtrans_abort(interp, oldcontext, oldowner);
21952207

2196-
free(qdesc->argtypes);
2197-
free(qdesc->arginfuncs);
2198-
free(qdesc->argtypioparams);
2199-
free(qdesc);
2208+
MemoryContextDelete(plan_cxt);
22002209
ckfree((char *) args);
22012210

22022211
return TCL_ERROR;

0 commit comments

Comments
 (0)