Skip to content

Commit 56a9325

Browse files
committed
Fix handling of COMMENT for domain constraints
For a non-superuser, changing a comment on a domain constraint was leading to a cache lookup failure as the code tried to perform the ownership lookup on the constraint OID itself, thinking that it was a type, but this check needs to happen on the type the domain constraint relies on. As the type a domain constraint relies on can be guessed directly based on the constraint OID, first fetch its type OID and perform the ownership on it. This is broken since 7eca575, which has split the handling of comments for table constraints and domain constraints, so back-patch down to 9.5. Reported-by: Clemens Ladisch Author: Daniel Gustafsson, Michael Paquier Reviewed-by: Álvaro Herrera Discussion: https://postgr.es/m/15833-808e11904835d26f@postgresql.org Backpatch-through: 9.5
1 parent 6e1dc84 commit 56a9325

File tree

3 files changed

+52
-1
lines changed

3 files changed

+52
-1
lines changed

src/backend/catalog/objectaddress.c

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2247,10 +2247,32 @@ check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address,
22472247
case OBJECT_TYPE:
22482248
case OBJECT_DOMAIN:
22492249
case OBJECT_ATTRIBUTE:
2250-
case OBJECT_DOMCONSTRAINT:
22512250
if (!pg_type_ownercheck(address.objectId, roleid))
22522251
aclcheck_error_type(ACLCHECK_NOT_OWNER, address.objectId);
22532252
break;
2253+
case OBJECT_DOMCONSTRAINT:
2254+
{
2255+
HeapTuple tuple;
2256+
Oid contypid;
2257+
2258+
tuple = SearchSysCache1(CONSTROID,
2259+
ObjectIdGetDatum(address.objectId));
2260+
if (!HeapTupleIsValid(tuple))
2261+
elog(ERROR, "constraint with OID %u does not exist",
2262+
address.objectId);
2263+
2264+
contypid = ((Form_pg_constraint) GETSTRUCT(tuple))->contypid;
2265+
2266+
ReleaseSysCache(tuple);
2267+
2268+
/*
2269+
* Fallback to type ownership check in this case as this is
2270+
* what domain constraints rely on.
2271+
*/
2272+
if (!pg_type_ownercheck(contypid, roleid))
2273+
aclcheck_error_type(ACLCHECK_NOT_OWNER, contypid);
2274+
}
2275+
break;
22542276
case OBJECT_AGGREGATE:
22552277
case OBJECT_FUNCTION:
22562278
if (!pg_proc_ownercheck(address.objectId, roleid))

src/test/regress/input/constraints.source

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,10 @@ ALTER TABLE deferred_excl ADD EXCLUDE (f1 WITH =);
502502
DROP TABLE deferred_excl;
503503

504504
-- Comments
505+
-- Setup a low-level role to enforce non-superuser checks.
506+
CREATE ROLE regress_constraint_comments;
507+
SET SESSION AUTHORIZATION regress_constraint_comments;
508+
505509
CREATE TABLE constraint_comments_tbl (a int CONSTRAINT the_constraint CHECK (a > 0));
506510
CREATE DOMAIN constraint_comments_dom AS int CONSTRAINT the_constraint CHECK (value > 0);
507511

@@ -519,5 +523,16 @@ COMMENT ON CONSTRAINT the_constraint ON DOMAIN no_comments_dom IS 'another bad c
519523
COMMENT ON CONSTRAINT the_constraint ON constraint_comments_tbl IS NULL;
520524
COMMENT ON CONSTRAINT the_constraint ON DOMAIN constraint_comments_dom IS NULL;
521525

526+
-- unauthorized user
527+
RESET SESSION AUTHORIZATION;
528+
CREATE ROLE regress_constraint_comments_noaccess;
529+
SET SESSION AUTHORIZATION regress_constraint_comments_noaccess;
530+
COMMENT ON CONSTRAINT the_constraint ON constraint_comments_tbl IS 'no, the comment';
531+
COMMENT ON CONSTRAINT the_constraint ON DOMAIN constraint_comments_dom IS 'no, another comment';
532+
RESET SESSION AUTHORIZATION;
533+
522534
DROP TABLE constraint_comments_tbl;
523535
DROP DOMAIN constraint_comments_dom;
536+
537+
DROP ROLE regress_constraint_comments;
538+
DROP ROLE regress_constraint_comments_noaccess;

src/test/regress/output/constraints.source

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,9 @@ ERROR: could not create exclusion constraint "deferred_excl_f1_excl"
676676
DETAIL: Key (f1)=(3) conflicts with key (f1)=(3).
677677
DROP TABLE deferred_excl;
678678
-- Comments
679+
-- Setup a low-level role to enforce non-superuser checks.
680+
CREATE ROLE regress_constraint_comments;
681+
SET SESSION AUTHORIZATION regress_constraint_comments;
679682
CREATE TABLE constraint_comments_tbl (a int CONSTRAINT the_constraint CHECK (a > 0));
680683
CREATE DOMAIN constraint_comments_dom AS int CONSTRAINT the_constraint CHECK (value > 0);
681684
COMMENT ON CONSTRAINT the_constraint ON constraint_comments_tbl IS 'yes, the comment';
@@ -692,5 +695,16 @@ COMMENT ON CONSTRAINT the_constraint ON DOMAIN no_comments_dom IS 'another bad c
692695
ERROR: type "no_comments_dom" does not exist
693696
COMMENT ON CONSTRAINT the_constraint ON constraint_comments_tbl IS NULL;
694697
COMMENT ON CONSTRAINT the_constraint ON DOMAIN constraint_comments_dom IS NULL;
698+
-- unauthorized user
699+
RESET SESSION AUTHORIZATION;
700+
CREATE ROLE regress_constraint_comments_noaccess;
701+
SET SESSION AUTHORIZATION regress_constraint_comments_noaccess;
702+
COMMENT ON CONSTRAINT the_constraint ON constraint_comments_tbl IS 'no, the comment';
703+
ERROR: must be owner of relation constraint_comments_tbl
704+
COMMENT ON CONSTRAINT the_constraint ON DOMAIN constraint_comments_dom IS 'no, another comment';
705+
ERROR: must be owner of type constraint_comments_dom
706+
RESET SESSION AUTHORIZATION;
695707
DROP TABLE constraint_comments_tbl;
696708
DROP DOMAIN constraint_comments_dom;
709+
DROP ROLE regress_constraint_comments;
710+
DROP ROLE regress_constraint_comments_noaccess;

0 commit comments

Comments
 (0)