diff options
author | Alvaro Herrera | 2015-07-20 12:18:08 +0000 |
---|---|---|
committer | Alvaro Herrera | 2015-07-20 12:18:08 +0000 |
commit | 14ade020ffa805b8335af10a11520b7b2249c99e (patch) | |
tree | d85ea5abfe78cd90ffd77f5809b90f194220c9de | |
parent | 76fa354c533c1955cc5fdcbff4a82edac274174c (diff) |
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
-rw-r--r-- | src/pl/tcl/pltcl.c | 27 |
1 files changed, 18 insertions, 9 deletions
diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c index 48118467eb7..d5aea3e2782 100644 --- a/src/pl/tcl/pltcl.c +++ b/src/pl/tcl/pltcl.c @@ -2031,6 +2031,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; @@ -2060,13 +2061,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 @@ -2094,7 +2106,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; } @@ -2125,10 +2137,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; |