pg.ddx.io  pgsql-hackers@postgresql.org mailing list archive  
help / color / mirror / Atom feed
StatisticsObjIsVisibleExt lacks "do not look in temp namespace"
2+ messages / 2 participants
[nested] [flat]

* StatisticsObjIsVisibleExt lacks "do not look in temp namespace"
@ 2025-09-20 16:21 Noah Misch <noah@leadboat.com>
  2025-09-22 14:12 ` Re: StatisticsObjIsVisibleExt lacks "do not look in temp namespace" Nathan Bossart <nathandbossart@gmail.com>
  0 siblings, 1 reply; 2+ messages in thread

From: Noah Misch @ 2025-09-20 16:21 UTC (permalink / raw)
  To: pgsql-hackers

StatisticsObjIsVisibleExt() lacks the "do not look in temp namespace" code of
the rest of the non-relation, non-type namespace searches.  Patch attached.
See its log messages for the consequences.

Incidentally, stats on temp tables do default to a permanent schema.  That
seems fine, though:

set search_path = public;
CREATE TEMP TABLE ab1 (a INTEGER, b INTEGER, c INTEGER);
CREATE STATISTICS s ON a, b FROM ab1;  -- creates public.s
\dX *.*
From: Noah Misch <noah@leadboat.com>

Fix StatisticsObjIsVisibleExt() for pg_temp.

Neighbor get_statistics_object_oid() ignores objects in pg_temp, as has
been the standard for non-relation, non-type namespace searches since
CVE-2007-2138.  Hence, most operations that name a statistics object
correctly decline to map an unqualified name to a statistics object in
pg_temp.  StatisticsObjIsVisibleExt() did not.  Consequently,
pg_statistics_obj_is_visible() wrongly returned true for such objects,
psql \dX wrongly listed them, and getObjectDescription()-based ereport()
and pg_describe_object() wrongly omitted namespace qualification.  Any
malfunction beyond that would depend on how a human or application acts
on those wrong indications.  Commit
d99d58cdc8c0b5b50ee92995e8575c100b1a458a introduced this.  Back-patch to
v13 (all supported versions).

Reviewed-by: FIXME
Discussion: https://postgr.es/m/FIXME
Backpatch-through: 13

diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
index 8bd4d6c..c1e7625 100644
--- a/src/backend/catalog/namespace.c
+++ b/src/backend/catalog/namespace.c
@@ -2685,6 +2685,9 @@ StatisticsObjIsVisibleExt(Oid stxid, bool *is_missing)
 		{
 			Oid			namespaceId = lfirst_oid(l);
 
+			if (namespaceId == myTempNamespace)
+				continue;		/* do not look in temp namespace */
+
 			if (namespaceId == stxnamespace)
 			{
 				/* Found it first in path */
diff --git a/src/test/regress/expected/stats_ext.out b/src/test/regress/expected/stats_ext.out
index a1f83b5..ff89dc4 100644
--- a/src/test/regress/expected/stats_ext.out
+++ b/src/test/regress/expected/stats_ext.out
@@ -129,6 +129,20 @@ ALTER STATISTICS ab1_a_b_stats RENAME TO ab1_a_b_stats_new;
 ERROR:  must be owner of statistics object ab1_a_b_stats
 RESET SESSION AUTHORIZATION;
 DROP ROLE regress_stats_ext;
+CREATE STATISTICS pg_temp.stats_ext_temp ON a, b FROM ab1;
+SELECT regexp_replace(pg_describe_object(tableoid, oid, 0),
+                      'pg_temp_[0-9]*', 'pg_temp_REDACTED') AS descr,
+       pg_statistics_obj_is_visible(oid) AS visible
+  FROM pg_statistic_ext
+ WHERE stxname = 'stats_ext_temp';
+                       descr                       | visible 
+---------------------------------------------------+---------
+ statistics object pg_temp_REDACTED.stats_ext_temp | f
+(1 row)
+
+DROP STATISTICS stats_ext_temp;  -- shall fail
+ERROR:  statistics object "stats_ext_temp" does not exist
+DROP STATISTICS pg_temp.stats_ext_temp;
 CREATE STATISTICS IF NOT EXISTS ab1_a_b_stats ON a, b FROM ab1;
 NOTICE:  statistics object "ab1_a_b_stats" already exists, skipping
 DROP STATISTICS ab1_a_b_stats;
diff --git a/src/test/regress/sql/stats_ext.sql b/src/test/regress/sql/stats_ext.sql
index 823c7db..acbb4f9 100644
--- a/src/test/regress/sql/stats_ext.sql
+++ b/src/test/regress/sql/stats_ext.sql
@@ -83,6 +83,14 @@ DROP STATISTICS ab1_a_b_stats;
 ALTER STATISTICS ab1_a_b_stats RENAME TO ab1_a_b_stats_new;
 RESET SESSION AUTHORIZATION;
 DROP ROLE regress_stats_ext;
+CREATE STATISTICS pg_temp.stats_ext_temp ON a, b FROM ab1;
+SELECT regexp_replace(pg_describe_object(tableoid, oid, 0),
+                      'pg_temp_[0-9]*', 'pg_temp_REDACTED') AS descr,
+       pg_statistics_obj_is_visible(oid) AS visible
+  FROM pg_statistic_ext
+ WHERE stxname = 'stats_ext_temp';
+DROP STATISTICS stats_ext_temp;  -- shall fail
+DROP STATISTICS pg_temp.stats_ext_temp;
 
 CREATE STATISTICS IF NOT EXISTS ab1_a_b_stats ON a, b FROM ab1;
 DROP STATISTICS ab1_a_b_stats;

Attachments:

  [text/plain] stats-ext-visible-v1.patch (3.4K, ../../20250920162116.2e.nmisch@google.com/2-stats-ext-visible-v1.patch)
  download | inline diff:
From: Noah Misch <noah@leadboat.com>

Fix StatisticsObjIsVisibleExt() for pg_temp.

Neighbor get_statistics_object_oid() ignores objects in pg_temp, as has
been the standard for non-relation, non-type namespace searches since
CVE-2007-2138.  Hence, most operations that name a statistics object
correctly decline to map an unqualified name to a statistics object in
pg_temp.  StatisticsObjIsVisibleExt() did not.  Consequently,
pg_statistics_obj_is_visible() wrongly returned true for such objects,
psql \dX wrongly listed them, and getObjectDescription()-based ereport()
and pg_describe_object() wrongly omitted namespace qualification.  Any
malfunction beyond that would depend on how a human or application acts
on those wrong indications.  Commit
d99d58cdc8c0b5b50ee92995e8575c100b1a458a introduced this.  Back-patch to
v13 (all supported versions).

Reviewed-by: FIXME
Discussion: https://postgr.es/m/FIXME
Backpatch-through: 13

diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
index 8bd4d6c..c1e7625 100644
--- a/src/backend/catalog/namespace.c
+++ b/src/backend/catalog/namespace.c
@@ -2685,6 +2685,9 @@ StatisticsObjIsVisibleExt(Oid stxid, bool *is_missing)
 		{
 			Oid			namespaceId = lfirst_oid(l);
 
+			if (namespaceId == myTempNamespace)
+				continue;		/* do not look in temp namespace */
+
 			if (namespaceId == stxnamespace)
 			{
 				/* Found it first in path */
diff --git a/src/test/regress/expected/stats_ext.out b/src/test/regress/expected/stats_ext.out
index a1f83b5..ff89dc4 100644
--- a/src/test/regress/expected/stats_ext.out
+++ b/src/test/regress/expected/stats_ext.out
@@ -129,6 +129,20 @@ ALTER STATISTICS ab1_a_b_stats RENAME TO ab1_a_b_stats_new;
 ERROR:  must be owner of statistics object ab1_a_b_stats
 RESET SESSION AUTHORIZATION;
 DROP ROLE regress_stats_ext;
+CREATE STATISTICS pg_temp.stats_ext_temp ON a, b FROM ab1;
+SELECT regexp_replace(pg_describe_object(tableoid, oid, 0),
+                      'pg_temp_[0-9]*', 'pg_temp_REDACTED') AS descr,
+       pg_statistics_obj_is_visible(oid) AS visible
+  FROM pg_statistic_ext
+ WHERE stxname = 'stats_ext_temp';
+                       descr                       | visible 
+---------------------------------------------------+---------
+ statistics object pg_temp_REDACTED.stats_ext_temp | f
+(1 row)
+
+DROP STATISTICS stats_ext_temp;  -- shall fail
+ERROR:  statistics object "stats_ext_temp" does not exist
+DROP STATISTICS pg_temp.stats_ext_temp;
 CREATE STATISTICS IF NOT EXISTS ab1_a_b_stats ON a, b FROM ab1;
 NOTICE:  statistics object "ab1_a_b_stats" already exists, skipping
 DROP STATISTICS ab1_a_b_stats;
diff --git a/src/test/regress/sql/stats_ext.sql b/src/test/regress/sql/stats_ext.sql
index 823c7db..acbb4f9 100644
--- a/src/test/regress/sql/stats_ext.sql
+++ b/src/test/regress/sql/stats_ext.sql
@@ -83,6 +83,14 @@ DROP STATISTICS ab1_a_b_stats;
 ALTER STATISTICS ab1_a_b_stats RENAME TO ab1_a_b_stats_new;
 RESET SESSION AUTHORIZATION;
 DROP ROLE regress_stats_ext;
+CREATE STATISTICS pg_temp.stats_ext_temp ON a, b FROM ab1;
+SELECT regexp_replace(pg_describe_object(tableoid, oid, 0),
+                      'pg_temp_[0-9]*', 'pg_temp_REDACTED') AS descr,
+       pg_statistics_obj_is_visible(oid) AS visible
+  FROM pg_statistic_ext
+ WHERE stxname = 'stats_ext_temp';
+DROP STATISTICS stats_ext_temp;  -- shall fail
+DROP STATISTICS pg_temp.stats_ext_temp;
 
 CREATE STATISTICS IF NOT EXISTS ab1_a_b_stats ON a, b FROM ab1;
 DROP STATISTICS ab1_a_b_stats;

^ permalink  raw  reply  [nested|flat] 2+ messages in thread

* Re: StatisticsObjIsVisibleExt lacks "do not look in temp namespace"
  2025-09-20 16:21 StatisticsObjIsVisibleExt lacks "do not look in temp namespace" Noah Misch <noah@leadboat.com>
@ 2025-09-22 14:12 ` Nathan Bossart <nathandbossart@gmail.com>
  0 siblings, 0 replies; 2+ messages in thread

From: Nathan Bossart @ 2025-09-22 14:12 UTC (permalink / raw)
  To: Noah Misch <noah@leadboat.com>; +Cc: pgsql-hackers

On Sat, Sep 20, 2025 at 09:21:16AM -0700, Noah Misch wrote:
> StatisticsObjIsVisibleExt() lacks the "do not look in temp namespace" code of
> the rest of the non-relation, non-type namespace searches.  Patch attached.

LGTM

-- 
nathan





^ permalink  raw  reply  [nested|flat] 2+ messages in thread


end of thread, other threads:[~2025-09-22 14:12 UTC | newest]

Thread overview: 2+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2025-09-20 16:21 StatisticsObjIsVisibleExt lacks "do not look in temp namespace" Noah Misch <noah@leadboat.com>
2025-09-22 14:12 ` Nathan Bossart <nathandbossart@gmail.com>

This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox