On 3/7/21 2:35 PM, Zhihong Yu wrote:
> Joe:
> I don't seem to find attachment.
>
> Maybe attach again ?
Oops -- I did forget that, didn't I. This time patch is attached :-)
Joe
--
Crunchy Data - http://crunchydata.com
PostgreSQL Support for Secure Enterprises
Consulting, Training, & Open Source Development
diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c
index c7f029e..152d1da 100644
*** a/src/backend/utils/adt/acl.c
--- b/src/backend/utils/adt/acl.c
*************** column_privilege_check(Oid tableoid, Att
*** 2460,2484 ****
return -1;
/*
! * First check if we have the privilege at the table level. We check
! * existence of the pg_class row before risking calling pg_class_aclcheck.
! * Note: it might seem there's a race condition against concurrent DROP,
! * but really it's safe because there will be no syscache flush between
! * here and there. So if we see the row in the syscache, so will
! * pg_class_aclcheck.
! */
! if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(tableoid)))
! return -1;
!
! aclresult = pg_class_aclcheck(tableoid, roleid, mode);
!
! if (aclresult == ACLCHECK_OK)
! return true;
!
! /*
! * No table privilege, so try per-column privileges. Again, we have to
! * check for dropped attribute first, and we rely on the syscache not to
! * notice a concurrent drop before pg_attribute_aclcheck fetches the row.
*/
attTuple = SearchSysCache2(ATTNUM,
ObjectIdGetDatum(tableoid),
--- 2460,2468 ----
return -1;
/*
! * We have to check for dropped attribute first, and we rely on the
! * syscache not to notice a concurrent drop before pg_attribute_aclcheck
! * fetches the row.
*/
attTuple = SearchSysCache2(ATTNUM,
ObjectIdGetDatum(tableoid),
*************** column_privilege_check(Oid tableoid, Att
*** 2493,2498 ****
--- 2477,2499 ----
}
ReleaseSysCache(attTuple);
+ /*
+ * Now check if we have the privilege at the table level. We check
+ * existence of the pg_class row before risking calling pg_class_aclcheck.
+ * Note: it might seem there's a race condition against concurrent DROP,
+ * but really it's safe because there will be no syscache flush between
+ * here and there. So if we see the row in the syscache, so will
+ * pg_class_aclcheck.
+ */
+ if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(tableoid)))
+ return -1;
+
+ aclresult = pg_class_aclcheck(tableoid, roleid, mode);
+
+ if (aclresult == ACLCHECK_OK)
+ return true;
+
+ /* no table privilege, so try per-column privilege */
aclresult = pg_attribute_aclcheck(tableoid, attnum, roleid, mode);
return (aclresult == ACLCHECK_OK);
diff --git a/src/test/regress/expected/privileges.out b/src/test/regress/expected/privileges.out
index 46a69fc..d60ea53 100644
*** a/src/test/regress/expected/privileges.out
--- b/src/test/regress/expected/privileges.out
*************** select has_column_privilege('mytable','.
*** 1362,1368 ****
select has_column_privilege('mytable',2::int2,'select');
has_column_privilege
----------------------
! t
(1 row)
revoke select on table mytable from regress_priv_user3;
--- 1362,1374 ----
select has_column_privilege('mytable',2::int2,'select');
has_column_privilege
----------------------
!
! (1 row)
!
! select has_column_privilege('mytable',99::int2,'select');
! has_column_privilege
! ----------------------
!
(1 row)
revoke select on table mytable from regress_priv_user3;
diff --git a/src/test/regress/sql/privileges.sql b/src/test/regress/sql/privileges.sql
index 6277140..766eeae 100644
*** a/src/test/regress/sql/privileges.sql
--- b/src/test/regress/sql/privileges.sql
*************** alter table mytable drop column f2;
*** 836,841 ****
--- 836,842 ----
select has_column_privilege('mytable','f2','select');
select has_column_privilege('mytable','........pg.dropped.2........','select');
select has_column_privilege('mytable',2::int2,'select');
+ select has_column_privilege('mytable',99::int2,'select');
revoke select on table mytable from regress_priv_user3;
select has_column_privilege('mytable',2::int2,'select');
drop table mytable;