mirror of
https://github.com/postgres/postgres.git
synced 2025-07-28 23:42:10 +03:00
Remove dependency to system calls for memory allocation in refint
Failures in allocations could lead to crashes with NULL pointer dereferences . Memory context TopMemoryContext is used instead to keep alive the plans allocated in the session. A more specific context could be used here, but this is left for later. Reported-by: Jian Zhang Author: Michael Paquier Reviewed-by: Tom Lane, Andres Freund Discussion: https://postgr.es/m/16190-70181c803641c3dc@postgresql.org
This commit is contained in:
@ -12,6 +12,7 @@
|
|||||||
#include "commands/trigger.h"
|
#include "commands/trigger.h"
|
||||||
#include "executor/spi.h"
|
#include "executor/spi.h"
|
||||||
#include "utils/builtins.h"
|
#include "utils/builtins.h"
|
||||||
|
#include "utils/memutils.h"
|
||||||
#include "utils/rel.h"
|
#include "utils/rel.h"
|
||||||
|
|
||||||
PG_MODULE_MAGIC;
|
PG_MODULE_MAGIC;
|
||||||
@ -186,12 +187,13 @@ check_primary_key(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Remember that SPI_prepare places plan in current memory context -
|
* Remember that SPI_prepare places plan in current memory context -
|
||||||
* so, we have to save plan in Top memory context for later use.
|
* so, we have to save plan in TopMemoryContext for later use.
|
||||||
*/
|
*/
|
||||||
if (SPI_keepplan(pplan))
|
if (SPI_keepplan(pplan))
|
||||||
/* internal error */
|
/* internal error */
|
||||||
elog(ERROR, "check_primary_key: SPI_keepplan failed");
|
elog(ERROR, "check_primary_key: SPI_keepplan failed");
|
||||||
plan->splan = (SPIPlanPtr *) malloc(sizeof(SPIPlanPtr));
|
plan->splan = (SPIPlanPtr *) MemoryContextAlloc(TopMemoryContext,
|
||||||
|
sizeof(SPIPlanPtr));
|
||||||
*(plan->splan) = pplan;
|
*(plan->splan) = pplan;
|
||||||
plan->nplans = 1;
|
plan->nplans = 1;
|
||||||
}
|
}
|
||||||
@ -417,7 +419,8 @@ check_foreign_key(PG_FUNCTION_ARGS)
|
|||||||
char sql[8192];
|
char sql[8192];
|
||||||
char **args2 = args;
|
char **args2 = args;
|
||||||
|
|
||||||
plan->splan = (SPIPlanPtr *) malloc(nrefs * sizeof(SPIPlanPtr));
|
plan->splan = (SPIPlanPtr *) MemoryContextAlloc(TopMemoryContext,
|
||||||
|
nrefs * sizeof(SPIPlanPtr));
|
||||||
|
|
||||||
for (r = 0; r < nrefs; r++)
|
for (r = 0; r < nrefs; r++)
|
||||||
{
|
{
|
||||||
@ -614,6 +617,13 @@ find_plan(char *ident, EPlan **eplan, int *nplans)
|
|||||||
{
|
{
|
||||||
EPlan *newp;
|
EPlan *newp;
|
||||||
int i;
|
int i;
|
||||||
|
MemoryContext oldcontext;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* All allocations done for the plans need to happen in a session-safe
|
||||||
|
* context.
|
||||||
|
*/
|
||||||
|
oldcontext = MemoryContextSwitchTo(TopMemoryContext);
|
||||||
|
|
||||||
if (*nplans > 0)
|
if (*nplans > 0)
|
||||||
{
|
{
|
||||||
@ -623,20 +633,24 @@ find_plan(char *ident, EPlan **eplan, int *nplans)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (i != *nplans)
|
if (i != *nplans)
|
||||||
|
{
|
||||||
|
MemoryContextSwitchTo(oldcontext);
|
||||||
return (*eplan + i);
|
return (*eplan + i);
|
||||||
*eplan = (EPlan *) realloc(*eplan, (i + 1) * sizeof(EPlan));
|
}
|
||||||
|
*eplan = (EPlan *) repalloc(*eplan, (i + 1) * sizeof(EPlan));
|
||||||
newp = *eplan + i;
|
newp = *eplan + i;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
newp = *eplan = (EPlan *) malloc(sizeof(EPlan));
|
newp = *eplan = (EPlan *) palloc(sizeof(EPlan));
|
||||||
(*nplans) = i = 0;
|
(*nplans) = i = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
newp->ident = strdup(ident);
|
newp->ident = pstrdup(ident);
|
||||||
newp->nplans = 0;
|
newp->nplans = 0;
|
||||||
newp->splan = NULL;
|
newp->splan = NULL;
|
||||||
(*nplans)++;
|
(*nplans)++;
|
||||||
|
|
||||||
|
MemoryContextSwitchTo(oldcontext);
|
||||||
return newp;
|
return newp;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user