postgres.git / summary / log / commit / refs

commit    efdb260728c93f605f9ef7aaef56b013f6bb87b7
Author:   Nathan Bossart <nathan@postgresql.org>
Commit:   Noah Misch <noah@leadboat.com>
Date:     Mon Aug 10 13:38:05 2026 +0000

    Check for USAGE privilege on the subtype in CREATE TYPE AS RANGE.
    
    This omission allowed roles without USAGE on a type to create range
    types that depend on it, which could prevent the owner from
    changing the type later.
    
    Reported-by: Jingzhou Fu <fuboat@outlook.com>
    Author: Nathan Bossart <nathandbossart@gmail.com>
    Reviewed-by: Noah Misch <noah@leadboat.com>
    Reviewed-by: Robert Haas <robertmhaas@gmail.com>
    Security: CVE-2026-6470
    Backpatch-through: 14


doc/src/sgml/ref/create_type.sgml | 5 +++++ src/backend/commands/typecmds.c | 4 ++++ src/test/regress/expected/rangetypes.out | 15 +++++++++++++++ src/test/regress/sql/rangetypes.sql | 14 ++++++++++++++ 4 files changed, 38 insertions(+) diff --git a/doc/src/sgml/ref/create_type.sgml b/doc/src/sgml/ref/create_type.sgml index 994dfc65268..6aa01eb0daa 100644 --- a/doc/src/sgml/ref/create_type.sgml +++ b/doc/src/sgml/ref/create_type.sgml @@ -186,6 +186,11 @@ CREATE TYPE <replaceable class="parameter">name</replaceable> type name. Otherwise, the multirange type name is formed by appending a <literal>_multirange</literal> suffix to the range type name. </para> + + <para> + To be able to create a range type, you must have <literal>USAGE</literal> + privilege on the subtype. + </para> </refsect2> <refsect2> diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c index e9c3215ccec..1d74a6e9457 100644 --- a/src/backend/commands/typecmds.c +++ b/src/backend/commands/typecmds.c @@ -1521,6 +1521,10 @@ DefineRange(ParseState *pstate, CreateRangeStmt *stmt) errmsg("range subtype cannot be %s", format_type_be(rangeSubtype)))); + aclresult = object_aclcheck(TypeRelationId, rangeSubtype, GetUserId(), ACL_USAGE); + if (aclresult != ACLCHECK_OK) + aclcheck_error_type(aclresult, rangeSubtype); + /* Identify subopclass */ rangeSubOpclass = findRangeSubOpclass(rangeSubOpclassName, rangeSubtype); diff --git a/src/test/regress/expected/rangetypes.out b/src/test/regress/expected/rangetypes.out index e062a4e5c2c..aecd12bd232 100644 --- a/src/test/regress/expected/rangetypes.out +++ b/src/test/regress/expected/rangetypes.out @@ -1601,6 +1601,21 @@ ERROR: range lower bound must be less than or equal to range upper bound LINE 1: select '[2010-01-01 01:00:00 -08, 2010-01-01 02:00:00 -05)':... ^ set timezone to default; +-- CREATE TYPE AS RANGE checks for USAGE on subtype +CREATE ROLE regress_subtype; +CREATE TYPE mytype AS (a INT, b INT); +REVOKE USAGE ON TYPE mytype FROM PUBLIC; +SET ROLE regress_subtype; +CREATE TYPE myrange AS RANGE (subtype = mytype); +ERROR: permission denied for type mytype +RESET ROLE; +GRANT USAGE ON TYPE mytype TO regress_subtype; +SET ROLE regress_subtype; +CREATE TYPE myrange AS RANGE (subtype = mytype); +RESET ROLE; +DROP TYPE mytype CASCADE; +NOTICE: drop cascades to type myrange +DROP ROLE regress_subtype; -- -- Test user-defined range of floats -- (type float8range was already made in test_setup.sql) diff --git a/src/test/regress/sql/rangetypes.sql b/src/test/regress/sql/rangetypes.sql index 5c4b0337b7a..7c917c60f46 100644 --- a/src/test/regress/sql/rangetypes.sql +++ b/src/test/regress/sql/rangetypes.sql @@ -444,6 +444,20 @@ select '[2010-01-01 01:00:00 -05, 2010-01-01 02:00:00 -08)'::tstzrange; select '[2010-01-01 01:00:00 -08, 2010-01-01 02:00:00 -05)'::tstzrange; set timezone to default; +-- CREATE TYPE AS RANGE checks for USAGE on subtype +CREATE ROLE regress_subtype; +CREATE TYPE mytype AS (a INT, b INT); +REVOKE USAGE ON TYPE mytype FROM PUBLIC; +SET ROLE regress_subtype; +CREATE TYPE myrange AS RANGE (subtype = mytype); +RESET ROLE; +GRANT USAGE ON TYPE mytype TO regress_subtype; +SET ROLE regress_subtype; +CREATE TYPE myrange AS RANGE (subtype = mytype); +RESET ROLE; +DROP TYPE mytype CASCADE; +DROP ROLE regress_subtype; + -- -- Test user-defined range of floats -- (type float8range was already made in test_setup.sql) [parent: 62c31b490d94]