-<!-- $PostgreSQL: pgsql/doc/src/sgml/release.sgml,v 1.500 2007/04/19 13:02:49 momjian Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/release.sgml,v 1.501 2007/04/20 02:37:37 tgl Exp $ -->
<!--
Typical markup:
</note>
<para>
- This release contains fixes from 8.2.3.
+ This release contains a variety of fixes from 8.2.3,
+ including a security fix.
</para>
<sect2>
<listitem>
<para>
- Fix <varname>shared_preload_libraries</> for Win32 by forcing reload in each backend
- (Korry Douglas)
+ Support explicit placement of the temporary-table schema within
+ <varname>search_path</>, and disable searching it for functions
+ and operators (Tom)
+ </para>
+ <para>
+ This is needed to allow a security-definer function to set a
+ truly secure value of <varname>search_path</>. Without it,
+ an unprivileged SQL user can use temporary objects to execute code
+ with the privileges of the security-definer function (CVE-2007-2138).
+ See <xref linkend="sql-createfunction"
+ endterm="sql-createfunction-title"> for more information.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Fix <varname>shared_preload_libraries</> for Windows
+ by forcing reload in each backend (Korry Douglas)
</para>
</listitem>
<listitem>
<para>
- <filename>/contrib/tsearch2</> fixes (Teodor)
+ <filename>/contrib/tsearch2</> crash fixes (Teodor)
</para>
</listitem>
<listitem>
<para>
- Require <command>COMMIT TRANSACTION</> to be executed in the same database as
- it was prepared (Heikki)
+ Require <command>COMMIT PREPARED</> to be executed in the same
+ database as the transaction was prepared in (Heikki)
</para>
</listitem>
<listitem>
<para>
- Allow Win32 <command>pg_dump</> to do binary backups larger than two gigabytes (Magnus)
+ Allow <command>pg_dump</> to do binary backups larger than two gigabytes
+ on Windows (Magnus)
</para>
</listitem>
<listitem>
<para>
- Improve detection of <acronym>POSIX</>-style time zone names (Tom)
+ Fix potential-data-corruption bug in how <command>VACUUM FULL</> handles
+ <command>UPDATE</> chains (Tom, Pavan Deolasee)
</para>
</listitem>
<listitem>
<para>
- Fix bug in how <command>VACUUM FULL</> handles <command>UPDATE</> chains (Tom, Pavan Deolasee)
+ Fix bug in domains that use array types (Tom)
</para>
</listitem>
<listitem>
<para>
- Fix bug in domains that use array types (Tom)
+ Fix <command>pg_dump</> so it can dump a serial column's sequence
+ using <option>-t</> when not also dumping the owning table
+ (Tom)
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Planner fixes, including improving outer join and bitmap scan
+ selection logic (Tom)
</para>
</listitem>
<listitem>
<para>
- Fix <command>pg_dump</> so it can dump a sequence using <option>-t</> when not also dumping the owning table
+ Fix possible wrong answers or crash when a PL/pgSQL function tries
+ to <literal>RETURN</> from within an <literal>EXCEPTION</> block
(Tom)
</para>
</listitem>
<listitem>
<para>
- Improve outer join and bitmap join selection logic (Tom)
+ Fix PANIC during enlargement of a hash index (Tom)
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Fix POSIX-style timezone specs to follow new USA DST rules (Tom)
</para>
</listitem>
</note>
<para>
- This release contains fixes from 8.1.8.
+ This release contains a variety of fixes from 8.1.8,
+ including a security fix.
</para>
<sect2>
<listitem>
<para>
- Fix <function>to_char()</> so it properly upper/lower cases localized day or month
- names (Pavel Stehule)
+ Support explicit placement of the temporary-table schema within
+ <varname>search_path</>, and disable searching it for functions
+ and operators (Tom)
+ </para>
+ <para>
+ This is needed to allow a security-definer function to set a
+ truly secure value of <varname>search_path</>. Without it,
+ an unprivileged SQL user can use temporary objects to execute code
+ with the privileges of the security-definer function (CVE-2007-2138).
+ See <xref linkend="sql-createfunction"
+ endterm="sql-createfunction-title"> for more information.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ <filename>/contrib/tsearch2</> crash fixes (Teodor)
</para>
</listitem>
<listitem>
<para>
- <filename>/contrib/tsearch2</> fixes (Teodor)
+ Require <command>COMMIT PREPARED</> to be executed in the same
+ database as the transaction was prepared in (Heikki)
</para>
</listitem>
<listitem>
<para>
- Require <command>COMMIT TRANSACTION</> to be executed in the same database as
- it was prepared (Heikki)
+ Fix potential-data-corruption bug in how <command>VACUUM FULL</> handles
+ <command>UPDATE</> chains (Tom, Pavan Deolasee)
</para>
</listitem>
<listitem>
<para>
- Improve detection of <acronym>POSIX</>-style time zone names (Tom)
+ Planner fixes, including improving outer join and bitmap scan
+ selection logic (Tom)
</para>
</listitem>
<listitem>
<para>
- Fix bug in how <command>VACUUM FULL</> handles <command>UPDATE</> chains (Tom, Pavan Deolasee)
+ Fix PANIC during enlargement of a hash index (bug introduced in 8.1.6)
+ (Tom)
</para>
</listitem>
<listitem>
<para>
- Improve outer join and bitmap join selection logic (Tom)
+ Fix POSIX-style timezone specs to follow new USA DST rules (Tom)
</para>
</listitem>
</note>
<para>
- This release contains fixes from 8.0.12.
+ This release contains a variety of fixes from 8.0.12,
+ including a security fix.
</para>
<sect2>
<listitem>
<para>
- <filename>/contrib/tsearch2</> fixes (Teodor)
+ Support explicit placement of the temporary-table schema within
+ <varname>search_path</>, and disable searching it for functions
+ and operators (Tom)
+ </para>
+ <para>
+ This is needed to allow a security-definer function to set a
+ truly secure value of <varname>search_path</>. Without it,
+ an unprivileged SQL user can use temporary objects to execute code
+ with the privileges of the security-definer function (CVE-2007-2138).
+ See <xref linkend="sql-createfunction"
+ endterm="sql-createfunction-title"> for more information.
</para>
</listitem>
<listitem>
<para>
- Improve detection of <acronym>POSIX</>-style time zone names (Tom)
+ <filename>/contrib/tsearch2</> crash fixes (Teodor)
</para>
</listitem>
<listitem>
<para>
- Fix bug in how <command>VACUUM FULL</> handles <command>UPDATE</> chains (Tom, Pavan Deolasee)
+ Fix potential-data-corruption bug in how <command>VACUUM FULL</> handles
+ <command>UPDATE</> chains (Tom, Pavan Deolasee)
</para>
</listitem>
<listitem>
<para>
- <filename>/contrib/tsearch2</> fixes (Teodor)
+ Fix PANIC during enlargement of a hash index (bug introduced in 8.0.10)
+ (Tom)
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Fix POSIX-style timezone specs to follow new USA DST rules (Tom)
</para>
</listitem>
</note>
<para>
- This release contains a variety of fixes from 7.4.16.
+ This release contains fixes from 7.4.16,
+ including a security fix.
</para>
<sect2>
<listitem>
<para>
- <filename>/contrib/tsearch2</> fixes (Teodor)
+ Support explicit placement of the temporary-table schema within
+ <varname>search_path</>, and disable searching it for functions
+ and operators (Tom)
+ </para>
+ <para>
+ This is needed to allow a security-definer function to set a
+ truly secure value of <varname>search_path</>. Without it,
+ an unprivileged SQL user can use temporary objects to execute code
+ with the privileges of the security-definer function (CVE-2007-2138).
+ See <xref linkend="sql-createfunction"
+ endterm="sql-createfunction-title"> for more information.
</para>
</listitem>
<listitem>
<para>
- Fix bug in how <command>VACUUM FULL</> handles <command>UPDATE</> chains (Tom, Pavan Deolasee)
+ <filename>/contrib/tsearch2</> crash fixes (Teodor)
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Fix potential-data-corruption bug in how <command>VACUUM FULL</> handles
+ <command>UPDATE</> chains (Tom, Pavan Deolasee)
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Fix PANIC during enlargement of a hash index (bug introduced in 7.4.15)
+ (Tom)
</para>
</listitem>
</note>
<para>
- This release contains a variety of fixes from 7.3.18.
+ This release contains fixes from 7.3.18,
+ including a security fix.
</para>
<sect2>
<listitem>
<para>
- Fix bug in how <command>VACUUM FULL</> handles <command>UPDATE</> chains (Tom, Pavan Deolasee)
+ Support explicit placement of the temporary-table schema within
+ <varname>search_path</>, and disable searching it for functions
+ and operators (Tom)
+ </para>
+ <para>
+ This is needed to allow a security-definer function to set a
+ truly secure value of <varname>search_path</>. Without it,
+ an unprivileged SQL user can use temporary objects to execute code
+ with the privileges of the security-definer function (CVE-2007-2138).
+ See <xref linkend="sql-createfunction"
+ endterm="sql-createfunction-title"> for more information.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Fix potential-data-corruption bug in how <command>VACUUM FULL</> handles
+ <command>UPDATE</> chains (Tom, Pavan Deolasee)
</para>
</listitem>
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/catalog/namespace.c,v 1.95 2007/04/12 22:34:45 neilc Exp $
+ * $PostgreSQL: pgsql/src/backend/catalog/namespace.c,v 1.96 2007/04/20 02:37:37 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* SQL99. Also, this provides a way to search the system namespace first
* without thereby making it the default creation target namespace.)
*
+ * For security reasons, searches using the search path will ignore the temp
+ * namespace when searching for any object type other than relations and
+ * types. (We must allow types since temp tables have rowtypes.)
+ *
* The default creation target namespace is always the first element of the
* explicit list. If the explicit list is empty, there is no default target.
*
- * In bootstrap mode, the search path is set equal to 'pg_catalog', so that
+ * The textual specification of search_path can include "$user" to refer to
+ * the namespace named the same as the current user, if any. (This is just
+ * ignored if there is no such namespace.) Also, it can include "pg_temp"
+ * to refer to the current backend's temp namespace. This is usually also
+ * ignorable if the temp namespace hasn't been set up, but there's a special
+ * case: if "pg_temp" appears first then it should be the default creation
+ * target. We kluge this case a little bit so that the temp namespace isn't
+ * set up until the first attempt to create something in it. (The reason for
+ * klugery is that we can't create the temp namespace outside a transaction,
+ * but initial GUC processing of search_path happens outside a transaction.)
+ * activeTempCreationPending is TRUE if "pg_temp" appears first in the string
+ * but is not reflected in activeCreationNamespace because the namespace isn't
+ * set up yet.
+ *
+ * In bootstrap mode, the search path is set equal to "pg_catalog", so that
* the system namespace is the only one searched or inserted into.
- * initdb is also careful to set search_path to 'pg_catalog' for its
+ * initdb is also careful to set search_path to "pg_catalog" for its
* post-bootstrap standalone backend runs. Otherwise the default search
* path is determined by GUC. The factory default path contains the PUBLIC
* namespace (if it exists), preceded by the user's personal namespace
/* default place to create stuff; if InvalidOid, no default */
static Oid activeCreationNamespace = InvalidOid;
+/* if TRUE, activeCreationNamespace is wrong, it should be temp namespace */
+static bool activeTempCreationPending = false;
+
/* These variables are the values last derived from namespace_search_path: */
static List *baseSearchPath = NIL;
static Oid baseCreationNamespace = InvalidOid;
+static bool baseTempCreationPending = false;
+
static Oid namespaceUser = InvalidOid;
-/* The above three values are valid only if baseSearchPathValid */
+/* The above four values are valid only if baseSearchPathValid */
static bool baseSearchPathValid = true;
/* Override requests are remembered in a stack of OverrideStackEntry structs */
if (newRelation->schemaname)
{
+ /* check for pg_temp alias */
+ if (strcmp(newRelation->schemaname, "pg_temp") == 0)
+ {
+ /* Initialize temp namespace if first time through */
+ if (!OidIsValid(myTempNamespace))
+ InitTempTableNamespace();
+ return myTempNamespace;
+ }
/* use exact schema given */
namespaceId = GetSysCacheOid(NAMESPACENAME,
CStringGetDatum(newRelation->schemaname),
{
/* use the default creation namespace */
recomputeNamespacePath();
+ if (activeTempCreationPending)
+ {
+ /* Need to initialize temp namespace */
+ InitTempTableNamespace();
+ return myTempNamespace;
+ }
namespaceId = activeCreationNamespace;
if (!OidIsValid(namespaceId))
ereport(ERROR,
}
else
{
- /* Consider only procs that are in the search path */
+ /*
+ * Consider only procs that are in the search path and are not
+ * in the temp namespace.
+ */
ListCell *nsp;
foreach(nsp, activeSearchPath)
{
- if (procform->pronamespace == lfirst_oid(nsp))
+ if (procform->pronamespace == lfirst_oid(nsp) &&
+ procform->pronamespace != myTempNamespace)
break;
pathpos++;
}
Oid namespaceId = lfirst_oid(l);
int i;
+ if (namespaceId == myTempNamespace)
+ continue; /* do not look in temp namespace */
+
for (i = 0; i < catlist->n_members; i++)
{
HeapTuple opertup = &catlist->members[i]->tuple;
}
else
{
- /* Consider only opers that are in the search path */
+ /*
+ * Consider only opers that are in the search path and are not
+ * in the temp namespace.
+ */
ListCell *nsp;
foreach(nsp, activeSearchPath)
{
- if (operform->oprnamespace == lfirst_oid(nsp))
+ if (operform->oprnamespace == lfirst_oid(nsp) &&
+ operform->oprnamespace != myTempNamespace)
break;
pathpos++;
}
{
Oid namespaceId = lfirst_oid(l);
+ if (namespaceId == myTempNamespace)
+ continue; /* do not look in temp namespace */
+
opcid = GetSysCacheOid(CLAAMNAMENSP,
ObjectIdGetDatum(amid),
PointerGetDatum(opcname),
{
Oid namespaceId = lfirst_oid(l);
+ if (namespaceId == myTempNamespace)
+ continue; /* do not look in temp namespace */
+
opfid = GetSysCacheOid(OPFAMILYAMNAMENSP,
ObjectIdGetDatum(amid),
PointerGetDatum(opfname),
{
Oid namespaceId = lfirst_oid(l);
+ if (namespaceId == myTempNamespace)
+ continue; /* do not look in temp namespace */
+
conid = GetSysCacheOid(CONNAMENSP,
PointerGetDatum(conname),
ObjectIdGetDatum(namespaceId),
Oid namespaceId;
AclResult aclresult;
+ /* check for pg_temp alias */
+ if (strcmp(nspname, "pg_temp") == 0)
+ {
+ if (OidIsValid(myTempNamespace))
+ return myTempNamespace;
+ /*
+ * Since this is used only for looking up existing objects, there
+ * is no point in trying to initialize the temp namespace here;
+ * and doing so might create problems for some callers.
+ * Just fall through and give the "does not exist" error.
+ */
+ }
+
namespaceId = GetSysCacheOid(NAMESPACENAME,
CStringGetDatum(nspname),
0, 0, 0);
* LookupCreationNamespace
* Look up the schema and verify we have CREATE rights on it.
*
- * This is just like LookupExplicitNamespace except for the permission check.
+ * This is just like LookupExplicitNamespace except for the permission check,
+ * and that we are willing to create pg_temp if needed.
+ *
+ * Note: calling this may result in a CommandCounterIncrement operation,
+ * if we have to create or clean out the temp namespace.
*/
Oid
LookupCreationNamespace(const char *nspname)
Oid namespaceId;
AclResult aclresult;
+ /* check for pg_temp alias */
+ if (strcmp(nspname, "pg_temp") == 0)
+ {
+ /* Initialize temp namespace if first time through */
+ if (!OidIsValid(myTempNamespace))
+ InitTempTableNamespace();
+ return myTempNamespace;
+ }
+
namespaceId = GetSysCacheOid(NAMESPACENAME,
CStringGetDatum(nspname),
0, 0, 0);
* Note: this does not apply any permissions check. Callers must check
* for CREATE rights on the selected namespace when appropriate.
*
- * This is *not* used for tables. Hence, the TEMP table namespace is
- * never selected as the creation target.
+ * Note: calling this may result in a CommandCounterIncrement operation,
+ * if we have to create or clean out the temp namespace.
*/
Oid
QualifiedNameGetCreationNamespace(List *names, char **objname_p)
{
char *schemaname;
- char *objname;
Oid namespaceId;
/* deconstruct the name list */
- DeconstructQualifiedName(names, &schemaname, &objname);
+ DeconstructQualifiedName(names, &schemaname, objname_p);
if (schemaname)
{
+ /* check for pg_temp alias */
+ if (strcmp(schemaname, "pg_temp") == 0)
+ {
+ /* Initialize temp namespace if first time through */
+ if (!OidIsValid(myTempNamespace))
+ InitTempTableNamespace();
+ return myTempNamespace;
+ }
/* use exact schema given */
namespaceId = GetSysCacheOid(NAMESPACENAME,
CStringGetDatum(schemaname),
{
/* use the default creation namespace */
recomputeNamespacePath();
+ if (activeTempCreationPending)
+ {
+ /* Need to initialize temp namespace */
+ InitTempTableNamespace();
+ return myTempNamespace;
+ }
namespaceId = activeCreationNamespace;
if (!OidIsValid(namespaceId))
ereport(ERROR,
errmsg("no schema has been selected to create in")));
}
- *objname_p = objname;
return namespaceId;
}
/* And make it active. */
activeSearchPath = entry->searchPath;
activeCreationNamespace = entry->creationNamespace;
+ activeTempCreationPending = false; /* XXX is this OK? */
MemoryContextSwitchTo(oldcxt);
}
entry = (OverrideStackEntry *) linitial(overrideStack);
activeSearchPath = entry->searchPath;
activeCreationNamespace = entry->creationNamespace;
+ activeTempCreationPending = false; /* XXX is this OK? */
}
else
{
/* If not baseSearchPathValid, this is useless but harmless */
activeSearchPath = baseSearchPath;
activeCreationNamespace = baseCreationNamespace;
+ activeTempCreationPending = baseTempCreationPending;
}
}
foreach(l, activeSearchPath)
{
namespaceId = lfirst_oid(l);
+
+ if (namespaceId == myTempNamespace)
+ continue; /* do not look in temp namespace */
+
conoid = FindConversion(conversion_name, namespaceId);
if (OidIsValid(conoid))
return conoid;
{
Oid namespaceId = lfirst_oid(l);
+ if (namespaceId == myTempNamespace)
+ continue; /* do not look in temp namespace */
+
proc = FindDefaultConversion(namespaceId, for_encoding, to_encoding);
if (OidIsValid(proc))
return proc;
List *oidlist;
List *newpath;
ListCell *l;
+ bool temp_missing;
Oid firstNS;
MemoryContext oldcxt;
* already been accepted.) Don't make duplicate entries, either.
*/
oidlist = NIL;
+ temp_missing = false;
foreach(l, namelist)
{
char *curname = (char *) lfirst(l);
oidlist = lappend_oid(oidlist, namespaceId);
}
}
+ else if (strcmp(curname, "pg_temp") == 0)
+ {
+ /* pg_temp --- substitute temp namespace, if any */
+ if (OidIsValid(myTempNamespace))
+ {
+ if (!list_member_oid(oidlist, myTempNamespace))
+ oidlist = lappend_oid(oidlist, myTempNamespace);
+ }
+ else
+ {
+ /* If it ought to be the creation namespace, set flag */
+ if (oidlist == NIL)
+ temp_missing = true;
+ }
+ }
else
{
/* normal namespace reference */
}
/*
- * Remember the first member of the explicit list.
+ * Remember the first member of the explicit list. (Note: this is
+ * nominally wrong if temp_missing, but we need it anyway to distinguish
+ * explicit from implicit mention of pg_catalog.)
*/
if (oidlist == NIL)
firstNS = InvalidOid;
list_free(baseSearchPath);
baseSearchPath = newpath;
baseCreationNamespace = firstNS;
+ baseTempCreationPending = temp_missing;
/* Mark the path valid. */
baseSearchPathValid = true;
/* And make it active. */
activeSearchPath = baseSearchPath;
activeCreationNamespace = baseCreationNamespace;
+ activeTempCreationPending = baseTempCreationPending;
/* Clean up. */
pfree(rawname);
char namespaceName[NAMEDATALEN];
Oid namespaceId;
+ Assert(!OidIsValid(myTempNamespace));
+
/*
* First, do permission check to see if we are authorized to make temp
* tables. We use a nonstandard error message here since "databasename:
baseSearchPathValid = false; /* need to rebuild list */
}
-/*
- * Remove all temp tables from the temporary namespace.
- */
-void
-ResetTempTableNamespace(void)
-{
- if (OidIsValid(myTempNamespace))
- RemoveTempRelations(myTempNamespace);
-}
-
/*
* End-of-transaction cleanup for namespaces.
*/
/* If not baseSearchPathValid, this is useless but harmless */
activeSearchPath = baseSearchPath;
activeCreationNamespace = baseCreationNamespace;
+ activeTempCreationPending = baseTempCreationPending;
}
}
entry = (OverrideStackEntry *) linitial(overrideStack);
activeSearchPath = entry->searchPath;
activeCreationNamespace = entry->creationNamespace;
+ activeTempCreationPending = false; /* XXX is this OK? */
}
else
{
/* If not baseSearchPathValid, this is useless but harmless */
activeSearchPath = baseSearchPath;
activeCreationNamespace = baseCreationNamespace;
+ activeTempCreationPending = baseTempCreationPending;
}
}
}
}
+/*
+ * Remove all temp tables from the temporary namespace.
+ */
+void
+ResetTempTableNamespace(void)
+{
+ if (OidIsValid(myTempNamespace))
+ RemoveTempRelations(myTempNamespace);
+}
+
/*
* Routines for handling the GUC variable 'search_path'.
{
/*
* Verify that all the names are either valid namespace names or
- * "$user". We do not require $user to correspond to a valid
- * namespace. We do not check for USAGE rights, either; should we?
+ * "$user" or "pg_temp". We do not require $user to correspond to a
+ * valid namespace, and pg_temp might not exist yet. We do not check
+ * for USAGE rights, either; should we?
*
* When source == PGC_S_TEST, we are checking the argument of an ALTER
* DATABASE SET or ALTER USER SET command. It could be that the
if (strcmp(curname, "$user") == 0)
continue;
+ if (strcmp(curname, "pg_temp") == 0)
+ continue;
if (!SearchSysCacheExists(NAMESPACENAME,
CStringGetDatum(curname),
0, 0, 0))
baseSearchPath = list_make1_oid(PG_CATALOG_NAMESPACE);
MemoryContextSwitchTo(oldcxt);
baseCreationNamespace = PG_CATALOG_NAMESPACE;
+ baseTempCreationPending = false;
baseSearchPathValid = true;
namespaceUser = GetUserId();
activeSearchPath = baseSearchPath;
activeCreationNamespace = baseCreationNamespace;
+ activeTempCreationPending = baseTempCreationPending;
}
else
{
*
* The returned list includes the implicitly-prepended namespaces only if
* includeImplicit is true.
+ *
+ * Note: calling this may result in a CommandCounterIncrement operation,
+ * if we have to create or clean out the temp namespace.
*/
List *
fetch_search_path(bool includeImplicit)
recomputeNamespacePath();
+ /*
+ * If the temp namespace should be first, force it to exist. This is
+ * so that callers can trust the result to reflect the actual default
+ * creation namespace. It's a bit bogus to do this here, since
+ * current_schema() is supposedly a stable function without side-effects,
+ * but the alternatives seem worse.
+ */
+ if (activeTempCreationPending)
+ {
+ InitTempTableNamespace();
+ recomputeNamespacePath();
+ }
+
result = list_copy(activeSearchPath);
if (!includeImplicit)
{