Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1v00L3-009S2p-Ie for pgsql-hackers@arkaria.postgresql.org; Sat, 20 Sep 2025 16:21:29 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1v00L0-00DQVz-TH for pgsql-hackers@arkaria.postgresql.org; Sat, 20 Sep 2025 16:21:26 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1v00L0-00DQVq-Cg for pgsql-hackers@lists.postgresql.org; Sat, 20 Sep 2025 16:21:26 +0000 Received: from mail-pf1-x436.google.com ([2607:f8b0:4864:20::436]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.96) (envelope-from ) id 1v00Kv-001tJw-1h for pgsql-hackers@postgresql.org; Sat, 20 Sep 2025 16:21:25 +0000 Received: by mail-pf1-x436.google.com with SMTP id d2e1a72fcca58-7761a8a1dbcso2832671b3a.1 for ; Sat, 20 Sep 2025 09:21:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=leadboat.com; s=google; t=1758385279; x=1758990079; darn=postgresql.org; h=user-agent:content-disposition:mime-version:message-id:subject:to :from:date:from:to:cc:subject:date:message-id:reply-to; bh=MNeSSB9v4XuHCbO8koRjrR2FllywRnpmZaQmte2g3iI=; b=Z29j+NIKwHjQ7Izn0EsmXfLc6sdETthES6pX+cWSIDrLA2f7evKKxu0iOqEKJzHauo XEYxud/mrPct5K1GuL7oKoB2e+CjfVy5q3WExwysfiNxjiH8ynFWqfuqw/BFNnOMhCXF FzW0sQniUneGzhELKZ+8RFDoOeCBcD+FRTGEw= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1758385279; x=1758990079; h=user-agent:content-disposition:mime-version:message-id:subject:to :from:date:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=MNeSSB9v4XuHCbO8koRjrR2FllywRnpmZaQmte2g3iI=; b=RTVeTwyHi9M9IuWygVjQyp6xrOTseuWxgOiW6sZYNKUuMf9JkR2uI9xgAXuBeLALl/ 3DWIe41t8VrpPX5wh05txIP8SPpXKp716KLJasuSu4H+EqinP5wLEPCQ6URDJCyt8+of a5LYdQ3fLI7wp2te9FfLnwz19Mwm8GsHGFZ8o4t5HHayGUFR7eV/hdJ5yduZ4YjEPQHu flI0zZQF7qiFca6rhgzWPbkdqjM/PlIbNUxJhVVRzRVIHhxlNERyz3FhKPkGfJ+iy/P7 tdqPhrkv3t1Cj3fnEXXwerU0jbtnf6Qch+8oA7GTxEr7RE+/ihrL/mOx5mE2sL5B9Uyp lG/w== X-Gm-Message-State: AOJu0YzskMD1rFZvhlkgtCK9enCyWaYRajrMQHpyh6P27teuymbctcji HpG56uGV2DpZ5bcrqjY1Q8uozITGRjEzbz2erYWTCVwYNcY8jJWMRhR13R5ihF7TXqO5xD54vxd 6lrk= X-Gm-Gg: ASbGncsGnNOD++XVStMmeP8rgdtXT3P8AGs9Zt/hKAeiW+p55vpPeIIQzSVHmM3XLUl LeVf+hRTdoAD97zpUkGp8JatVayS6rUPtTCGXvpD+/wqk3ALmxjw7mIC659vlj2W5pW1NQxxE65 c6ylqKFmyrii6knVhbtdDfzIQ8OYYXApSI6aSrkDtXjNKZZIuIGb1gwW2IPNvygo1Na2z1htK/d eQ0tyPz1oz3kDlJbdaWBMhqRji0ReovgZbzqFy0Gldfb2t9exnyJSfb5cLJJXG7Hgq6gZTpCU6e U01v6ZQ19bAB6vr9/VwbLVBIduecclARfOVKRYjATw7Y+g2/ieDsvwJw2B3m4xC9Ikhim5cKu9y 0IeO/HwlLQN/2unY1gRo6lzzfECCZWcePEbqBKn6FPCUBdn0jUXk= X-Google-Smtp-Source: AGHT+IEu9nqr2IKxUZVs8Ug1gp7xFoDFkKbDrpT1aK0xGu4R2EwB3lpB1KeWd/6/5B+EPHfs0V0hHw== X-Received: by 2002:a05:6a00:cc7:b0:776:1804:6fe with SMTP id d2e1a72fcca58-77e4cc3c5e1mr7646698b3a.7.1758385278984; Sat, 20 Sep 2025 09:21:18 -0700 (PDT) Received: from google.com (c-73-15-160-255.hsd1.ca.comcast.net. [73.15.160.255]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-77f0da43089sm4005229b3a.90.2025.09.20.09.21.17 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Sat, 20 Sep 2025 09:21:17 -0700 (PDT) Date: Sat, 20 Sep 2025 09:21:16 -0700 From: Noah Misch To: pgsql-hackers@postgresql.org Subject: StatisticsObjIsVisibleExt lacks "do not look in temp namespace" Message-ID: <20250920162116.2e.nmisch@google.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="I7OwxbLnUCpS0TZx" Content-Disposition: inline User-Agent: Mutt/2.2.12 (2023-09-09) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --I7OwxbLnUCpS0TZx Content-Type: text/plain; charset=us-ascii Content-Disposition: inline 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 *.* --I7OwxbLnUCpS0TZx Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="stats-ext-visible-v1.patch" From: Noah Misch 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; --I7OwxbLnUCpS0TZx--