Don't access catalogs to validate GUCs when not connected to a DB.
authorAndres Freund <[email protected]>
Tue, 11 Jun 2019 06:20:48 +0000 (23:20 -0700)
committerAndres Freund <[email protected]>
Tue, 11 Jun 2019 06:37:02 +0000 (23:37 -0700)
Vignesh found this bug in the check function for
default_table_access_method's check hook, but that was just copied
from older GUCs. Investigation by Michael and me then found the bug in
further places.

When not connected to a database (e.g. in a walsender connection), we
cannot perform (most) GUC checks that need database access. Even when
only shared tables are needed, unless they're
nailed (c.f. RelationCacheInitializePhase2()), they cannot be accessed
without pg_class etc. being present.

Fix by extending the existing IsTransactionState() checks to also
check for MyDatabaseOid.

Reported-By: Vignesh C, Michael Paquier, Andres Freund
Author: Vignesh C, Andres Freund
Discussion: https://postgr.es/m/CALDaNm1KXK9gbZfY-p_peRFm_XrBh1OwQO1Kk6Gig0c0fVZ2uw%40mail.gmail.com
Backpatch: 9.4-

src/backend/commands/tablespace.c
src/backend/utils/cache/ts_cache.c

index 5012e8c8888535a53986bfa26687252b8bcb080b..bb15c582ff25bddab885da5f85f6ed4743acaab0 100644 (file)
@@ -1007,10 +1007,11 @@ bool
 check_default_tablespace(char **newval, void **extra, GucSource source)
 {
    /*
-    * If we aren't inside a transaction, we cannot do database access so
-    * cannot verify the name.  Must accept the value on faith.
+    * If we aren't inside a transaction, or connected to a database, we
+    * cannot do the catalog accesses necessary to verify the name.  Must
+    * accept the value on faith.
     */
-   if (IsTransactionState())
+   if (IsTransactionState() && MyDatabaseId != InvalidOid)
    {
        if (**newval != '\0' &&
            !OidIsValid(get_tablespace_oid(*newval, true)))
@@ -1118,11 +1119,12 @@ check_temp_tablespaces(char **newval, void **extra, GucSource source)
    }
 
    /*
-    * If we aren't inside a transaction, we cannot do database access so
-    * cannot verify the individual names.  Must accept the list on faith.
+    * If we aren't inside a transaction, or connected to a database, we
+    * cannot do the catalog accesses necessary to verify the name.  Must
+    * accept the value on faith.
     * Fortunately, there's then also no need to pass the data to fd.c.
     */
-   if (IsTransactionState())
+   if (IsTransactionState() && MyDatabaseId != InvalidOid)
    {
        temp_tablespaces_extra *myextra;
        Oid        *tblSpcs;
index 5ff1461f7d818de3643fbadd13312ed76c8d2e59..c605a6ecbd90490c4b0e01038959a2c93cffbd2c 100644 (file)
@@ -38,6 +38,7 @@
 #include "catalog/pg_ts_parser.h"
 #include "catalog/pg_ts_template.h"
 #include "commands/defrem.h"
+#include "miscadmin.h"
 #include "tsearch/ts_cache.h"
 #include "utils/builtins.h"
 #include "utils/catcache.h"
@@ -591,10 +592,11 @@ bool
 check_TSCurrentConfig(char **newval, void **extra, GucSource source)
 {
    /*
-    * If we aren't inside a transaction, we cannot do database access so
-    * cannot verify the config name.  Must accept it on faith.
+    * If we aren't inside a transaction, or connected to a database, we
+    * cannot do the catalog accesses necessary to verify the config name.
+    * Must accept it on faith.
     */
-   if (IsTransactionState())
+   if (IsTransactionState() && MyDatabaseId != InvalidOid)
    {
        Oid         cfgId;
        HeapTuple   tuple;