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;

Reply via email to