Commit f8d67ca8 authored by Alvaro Herrera's avatar Alvaro Herrera

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
parent 8d907369
......@@ -2104,6 +2104,7 @@ static int
pltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp,
int argc, CONST84 char *argv[])
{
volatile MemoryContext plan_cxt = NULL;
int nargs;
CONST84 char **args;
pltcl_query_desc *qdesc;
......@@ -2132,13 +2133,24 @@ pltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp,
/************************************************************
* Allocate the new querydesc structure
************************************************************/
qdesc = (pltcl_query_desc *) malloc(sizeof(pltcl_query_desc));
*
* struct qdesc and subsidiary data all live in plan_cxt. Note that if the
* function is recompiled for whatever reason, permanent memory leaks
* occur. FIXME someday.
************************************************************/
plan_cxt = AllocSetContextCreate(TopMemoryContext,
"PL/TCL spi_prepare query",
ALLOCSET_SMALL_MINSIZE,
ALLOCSET_SMALL_INITSIZE,
ALLOCSET_SMALL_MAXSIZE);
MemoryContextSwitchTo(plan_cxt);
qdesc = (pltcl_query_desc *) palloc0(sizeof(pltcl_query_desc));
snprintf(qdesc->qname, sizeof(qdesc->qname), "%p", qdesc);
qdesc->nargs = nargs;
qdesc->argtypes = (Oid *) malloc(nargs * sizeof(Oid));
qdesc->arginfuncs = (FmgrInfo *) malloc(nargs * sizeof(FmgrInfo));
qdesc->argtypioparams = (Oid *) malloc(nargs * sizeof(Oid));
qdesc->argtypes = (Oid *) palloc(nargs * sizeof(Oid));
qdesc->arginfuncs = (FmgrInfo *) palloc(nargs * sizeof(FmgrInfo));
qdesc->argtypioparams = (Oid *) palloc(nargs * sizeof(Oid));
MemoryContextSwitchTo(oldcontext);
/************************************************************
* Execute the prepare inside a sub-transaction, so we can cope with
......@@ -2166,7 +2178,7 @@ pltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp,
getTypeInputInfo(typId, &typInput, &typIOParam);
qdesc->argtypes[i] = typId;
perm_fmgr_info(typInput, &(qdesc->arginfuncs[i]));
fmgr_info_cxt(typInput, &(qdesc->arginfuncs[i]), plan_cxt);
qdesc->argtypioparams[i] = typIOParam;
}
......@@ -2193,10 +2205,7 @@ pltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp,
{
pltcl_subtrans_abort(interp, oldcontext, oldowner);
free(qdesc->argtypes);
free(qdesc->arginfuncs);
free(qdesc->argtypioparams);
free(qdesc);
MemoryContextDelete(plan_cxt);
ckfree((char *) args);
return TCL_ERROR;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment