aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlvaro Herrera <alvherre@alvh.no-ip.org>2015-07-20 14:18:08 +0200
committerAlvaro Herrera <alvherre@alvh.no-ip.org>2015-07-20 14:18:08 +0200
commit49c30004073fdb90800054cd1d13e5ab441f6283 (patch)
tree712f6b9cd78264222d38d0ef041dbb481f5da419 /src
parent29efe1b5ebc82512cae363349bae6dd22e9b00eb (diff)
downloadpostgresql-49c30004073fdb90800054cd1d13e5ab441f6283.tar.gz
postgresql-49c30004073fdb90800054cd1d13e5ab441f6283.zip
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
Diffstat (limited to 'src')
-rw-r--r--src/pl/tcl/pltcl.c27
1 files changed, 18 insertions, 9 deletions
diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c
index bb6994ce92d..81c91dd7854 100644
--- a/src/pl/tcl/pltcl.c
+++ b/src/pl/tcl/pltcl.c
@@ -2106,6 +2106,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;
@@ -2134,13 +2135,24 @@ pltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp,
/************************************************************
* Allocate the new querydesc structure
+ *
+ * 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.
************************************************************/
- qdesc = (pltcl_query_desc *) malloc(sizeof(pltcl_query_desc));
+ 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
@@ -2168,7 +2180,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;
}
@@ -2195,10 +2207,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;