From 28026681598526cea3bc50da93a4ab37a161be19 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 2 Dec 2002 05:20:47 +0000 Subject: [PATCH] Repair core dump when trying to delete an entry from an already-NULL datconfig or useconfig field. Per report from Dustin Sallings. --- src/backend/commands/dbcommands.c | 7 +++-- src/backend/commands/user.c | 9 ++++-- src/backend/utils/misc/guc.c | 50 +++++++++++++++++++++---------- 3 files changed, 46 insertions(+), 20 deletions(-) diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c index 291770f98c..f2973d6b16 100644 --- a/src/backend/commands/dbcommands.c +++ b/src/backend/commands/dbcommands.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.107 2002/11/02 18:41:21 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.108 2002/12/02 05:20:47 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -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); diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c index a9b1e5d05f..3bba3f6188 100644 --- a/src/backend/commands/user.c +++ b/src/backend/commands/user.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.113 2002/10/21 19:46:45 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.114 2002/12/02 05:20:47 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -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); diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index c26c4c7407..02c78e0de0 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -5,7 +5,7 @@ * command, configuration file, and command line options. * See src/backend/utils/misc/README for more information. * - * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.107 2002/11/21 00:42:19 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.108 2002/12/02 05:20:47 tgl Exp $ * * Copyright 2000 by PostgreSQL Global Development Group * Written by Peter Eisentraut . @@ -2754,7 +2754,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) @@ -2809,7 +2809,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) { @@ -2880,7 +2883,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) { @@ -2889,16 +2896,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++) @@ -2917,18 +2925,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++; }