Repair core dump when trying to delete an entry from an already-NULL
authorTom Lane <[email protected]>
Mon, 2 Dec 2002 05:21:02 +0000 (05:21 +0000)
committerTom Lane <[email protected]>
Mon, 2 Dec 2002 05:21:02 +0000 (05:21 +0000)
datconfig or useconfig field.  Per report from Dustin Sallings.

src/backend/commands/dbcommands.c
src/backend/commands/user.c
src/backend/utils/misc/guc.c

index a6383fcde354c49a74fb1d093c775604852c26a2..2ea3b80537d418c9da80cbd0eb40a6149be59498 100644 (file)
@@ -561,7 +561,10 @@ AlterDatabaseSet(AlterDatabaseSetStmt *stmt)
                else
                        a = GUCArrayDelete(a, stmt->variable);
 
-               repl_val[Anum_pg_database_datconfig - 1] = PointerGetDatum(a);
+               if (a)
+                       repl_val[Anum_pg_database_datconfig - 1] = PointerGetDatum(a);
+               else
+                       repl_null[Anum_pg_database_datconfig - 1] = 'n';
        }
 
        newtuple = heap_modifytuple(tuple, rel, repl_val, repl_null, repl_repl);
index c0c9073591ef32732ea4a78f621f76bd27a5566e..ce6b1b1a6152d5c69469ed6dc790079671a1d561 100644 (file)
@@ -915,8 +915,10 @@ AlterUserSet(AlterUserSetStmt *stmt)
 
        repl_repl[Anum_pg_shadow_useconfig - 1] = 'r';
        if (strcmp(stmt->variable, "all") == 0 && valuestr == NULL)
+       {
                /* RESET ALL */
                repl_null[Anum_pg_shadow_useconfig - 1] = 'n';
+       }
        else
        {
                Datum           datum;
@@ -935,7 +937,10 @@ AlterUserSet(AlterUserSetStmt *stmt)
                else
                        array = GUCArrayDelete(array, stmt->variable);
 
-               repl_val[Anum_pg_shadow_useconfig - 1] = PointerGetDatum(array);
+               if (array)
+                       repl_val[Anum_pg_shadow_useconfig - 1] = PointerGetDatum(array);
+               else
+                       repl_null[Anum_pg_shadow_useconfig - 1] = 'n';
        }
 
        newtuple = heap_modifytuple(oldtuple, rel, repl_val, repl_null, repl_repl);
index 4537213b11b1e88fe1c325f4c0aefaf9dc01aa21..26e78c74e0eff5fe2629ac7beeedd0acaff60cbd 100644 (file)
@@ -2740,7 +2740,7 @@ assign_defaultxactisolevel(const char *newval, bool doit, bool interactive)
 
 /*
  * Handle options fetched from pg_database.datconfig or pg_shadow.useconfig.
- * The array parameter must be an array of TEXT.
+ * The array parameter must be an array of TEXT (it must not be NULL).
  */
 void
 ProcessGUCArray(ArrayType *array, GucSource source)
@@ -2795,7 +2795,10 @@ ProcessGUCArray(ArrayType *array, GucSource source)
 }
 
 
-
+/*
+ * Add an entry to an option array.  The array parameter may be NULL
+ * to indicate the current table entry is NULL.
+ */
 ArrayType *
 GUCArrayAdd(ArrayType *array, const char *name, const char *value)
 {
@@ -2866,7 +2869,11 @@ GUCArrayAdd(ArrayType *array, const char *name, const char *value)
 }
 
 
-
+/*
+ * Delete an entry from an option array.  The array parameter may be NULL
+ * to indicate the current table entry is NULL.  Also, if the return value
+ * is NULL then a null should be stored.
+ */
 ArrayType *
 GUCArrayDelete(ArrayType *array, const char *name)
 {
@@ -2875,16 +2882,17 @@ GUCArrayDelete(ArrayType *array, const char *name)
        int                     index;
 
        Assert(name);
-       Assert(array);
 
        /* test if the option is valid */
        set_config_option(name, NULL,
                                          superuser() ? PGC_SUSET : PGC_USERSET,
                                          PGC_S_SESSION, false, false);
 
-       newarray = construct_array(NULL, 0,
-                                                          TEXTOID,
-                                                          -1, false, 'i');
+       /* if array is currently null, then surely nothing to delete */
+       if (!array)
+               return NULL;
+
+       newarray = NULL;
        index = 1;
 
        for (i = 1; i <= ARR_DIMS(array)[0]; i++)
@@ -2903,18 +2911,28 @@ GUCArrayDelete(ArrayType *array, const char *name)
                        continue;
                val = DatumGetCString(DirectFunctionCall1(textout, d));
 
+               /* ignore entry if it's what we want to delete */
                if (strncmp(val, name, strlen(name)) == 0
                        && val[strlen(name)] == '=')
                        continue;
 
-               isnull = false;
-               newarray = array_set(newarray, 1, &index,
-                                                        d,
-                                                        -1 /* varlenarray */ ,
-                                                        -1 /* TEXT's typlen */ ,
-                                                        false /* TEXT's typbyval */ ,
-                                                        'i' /* TEXT's typalign */ ,
-                                                        &isnull);
+               /* else add it to the output array */
+               if (newarray)
+               {
+                       isnull = false;
+                       newarray = array_set(newarray, 1, &index,
+                                                                d,
+                                                                -1 /* varlenarray */ ,
+                                                                -1 /* TEXT's typlen */ ,
+                                                                false /* TEXT's typbyval */ ,
+                                                                'i' /* TEXT's typalign */ ,
+                                                                &isnull);
+               }
+               else
+                       newarray = construct_array(&d, 1,
+                                                                          TEXTOID,
+                                                                          -1, false, 'i');
+
                index++;
        }