mirror of
https://github.com/postgres/postgres.git
synced 2025-05-17 06:41:24 +03:00
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
This commit is contained in:
parent
498a29dc32
commit
b2efbb71df
@ -2039,6 +2039,7 @@ static int
|
|||||||
pltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp,
|
pltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp,
|
||||||
int argc, CONST84 char *argv[])
|
int argc, CONST84 char *argv[])
|
||||||
{
|
{
|
||||||
|
volatile MemoryContext plan_cxt = NULL;
|
||||||
int nargs;
|
int nargs;
|
||||||
CONST84 char **args;
|
CONST84 char **args;
|
||||||
pltcl_query_desc *qdesc;
|
pltcl_query_desc *qdesc;
|
||||||
@ -2067,13 +2068,24 @@ pltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp,
|
|||||||
|
|
||||||
/************************************************************
|
/************************************************************
|
||||||
* Allocate the new querydesc structure
|
* 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);
|
snprintf(qdesc->qname, sizeof(qdesc->qname), "%p", qdesc);
|
||||||
qdesc->nargs = nargs;
|
qdesc->nargs = nargs;
|
||||||
qdesc->argtypes = (Oid *) malloc(nargs * sizeof(Oid));
|
qdesc->argtypes = (Oid *) palloc(nargs * sizeof(Oid));
|
||||||
qdesc->arginfuncs = (FmgrInfo *) malloc(nargs * sizeof(FmgrInfo));
|
qdesc->arginfuncs = (FmgrInfo *) palloc(nargs * sizeof(FmgrInfo));
|
||||||
qdesc->argtypioparams = (Oid *) malloc(nargs * sizeof(Oid));
|
qdesc->argtypioparams = (Oid *) palloc(nargs * sizeof(Oid));
|
||||||
|
MemoryContextSwitchTo(oldcontext);
|
||||||
|
|
||||||
/************************************************************
|
/************************************************************
|
||||||
* Execute the prepare inside a sub-transaction, so we can cope with
|
* Execute the prepare inside a sub-transaction, so we can cope with
|
||||||
@ -2101,7 +2113,7 @@ pltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp,
|
|||||||
getTypeInputInfo(typId, &typInput, &typIOParam);
|
getTypeInputInfo(typId, &typInput, &typIOParam);
|
||||||
|
|
||||||
qdesc->argtypes[i] = typId;
|
qdesc->argtypes[i] = typId;
|
||||||
perm_fmgr_info(typInput, &(qdesc->arginfuncs[i]));
|
fmgr_info_cxt(typInput, &(qdesc->arginfuncs[i]), plan_cxt);
|
||||||
qdesc->argtypioparams[i] = typIOParam;
|
qdesc->argtypioparams[i] = typIOParam;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2128,10 +2140,7 @@ pltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp,
|
|||||||
{
|
{
|
||||||
pltcl_subtrans_abort(interp, oldcontext, oldowner);
|
pltcl_subtrans_abort(interp, oldcontext, oldowner);
|
||||||
|
|
||||||
free(qdesc->argtypes);
|
MemoryContextDelete(plan_cxt);
|
||||||
free(qdesc->arginfuncs);
|
|
||||||
free(qdesc->argtypioparams);
|
|
||||||
free(qdesc);
|
|
||||||
ckfree((char *) args);
|
ckfree((char *) args);
|
||||||
|
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user