Remove dependency to system calls for memory allocation in refint
authorMichael Paquier <michael@paquier.xyz>
Wed, 8 Jan 2020 01:02:55 +0000 (10:02 +0900)
committerMichael Paquier <michael@paquier.xyz>
Wed, 8 Jan 2020 01:02:55 +0000 (10:02 +0900)
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

contrib/spi/refint.c

index adf0490f8539b0fa7ac5016052b9761021c5e225..6fbfef2b12167f46b0c58555f8e6a98afd8fbfac 100644 (file)
@@ -12,6 +12,7 @@
 #include "commands/trigger.h"
 #include "executor/spi.h"
 #include "utils/builtins.h"
+#include "utils/memutils.h"
 #include "utils/rel.h"
 
 PG_MODULE_MAGIC;
@@ -186,12 +187,13 @@ check_primary_key(PG_FUNCTION_ARGS)
 
        /*
         * 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))
            /* internal error */
            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->nplans = 1;
    }
@@ -417,7 +419,8 @@ check_foreign_key(PG_FUNCTION_ARGS)
        char        sql[8192];
        char      **args2 = args;
 
-       plan->splan = (SPIPlanPtr *) malloc(nrefs * sizeof(SPIPlanPtr));
+       plan->splan = (SPIPlanPtr *) MemoryContextAlloc(TopMemoryContext,
+                                                       nrefs * sizeof(SPIPlanPtr));
 
        for (r = 0; r < nrefs; r++)
        {
@@ -614,6 +617,13 @@ find_plan(char *ident, EPlan **eplan, int *nplans)
 {
    EPlan      *newp;
    int         i;
+   MemoryContext oldcontext;
+
+   /*
+    * All allocations done for the plans need to happen in a session-safe
+    * context.
+    */
+   oldcontext = MemoryContextSwitchTo(TopMemoryContext);
 
    if (*nplans > 0)
    {
@@ -623,20 +633,24 @@ find_plan(char *ident, EPlan **eplan, int *nplans)
                break;
        }
        if (i != *nplans)
+       {
+           MemoryContextSwitchTo(oldcontext);
            return (*eplan + i);
-       *eplan = (EPlan *) realloc(*eplan, (i + 1) * sizeof(EPlan));
+       }
+       *eplan = (EPlan *) repalloc(*eplan, (i + 1) * sizeof(EPlan));
        newp = *eplan + i;
    }
    else
    {
-       newp = *eplan = (EPlan *) malloc(sizeof(EPlan));
+       newp = *eplan = (EPlan *) palloc(sizeof(EPlan));
        (*nplans) = i = 0;
    }
 
-   newp->ident = strdup(ident);
+   newp->ident = pstrdup(ident);
    newp->nplans = 0;
    newp->splan = NULL;
    (*nplans)++;
 
+   MemoryContextSwitchTo(oldcontext);
    return newp;
 }