Fix possible future cache reference leak in ALTER EXTENSION ADD/DROP.

recordExtObjInitPriv and removeExtObjInitPriv were sloppy about
calling ReleaseSysCache.  The cases cannot occur given current usage
in ALTER EXTENSION ADD/DROP, since we wouldn't get here for these
relkinds; but it seems wise to clean up better.

In passing, extend test logic in test_pg_dump to exercise the
dropped-column code paths here.

Since the case is unreachable at present, there seems no great
need to back-patch; hence fix HEAD only.

Kyotaro Horiguchi, with test case and comment adjustments by me

Discussion: https://postgr.es/m/20200417.151831.1153577605111650154.horikyota.ntt@gmail.com
This commit is contained in:
Tom Lane 2020-04-17 13:41:59 -04:00
parent 4db819ba40
commit 3125a5baec
4 changed files with 35 additions and 20 deletions

View File

@ -5580,19 +5580,22 @@ recordExtObjInitPriv(Oid objoid, Oid classoid)
elog(ERROR, "cache lookup failed for relation %u", objoid); elog(ERROR, "cache lookup failed for relation %u", objoid);
pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple); pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple);
/* Indexes don't have permissions */ /*
* Indexes don't have permissions, neither do the pg_class rows for
* composite types. (These cases are unreachable given the
* restrictions in ALTER EXTENSION ADD, but let's check anyway.)
*/
if (pg_class_tuple->relkind == RELKIND_INDEX || if (pg_class_tuple->relkind == RELKIND_INDEX ||
pg_class_tuple->relkind == RELKIND_PARTITIONED_INDEX) pg_class_tuple->relkind == RELKIND_PARTITIONED_INDEX ||
return; pg_class_tuple->relkind == RELKIND_COMPOSITE_TYPE)
{
/* Composite types don't have permissions either */ ReleaseSysCache(tuple);
if (pg_class_tuple->relkind == RELKIND_COMPOSITE_TYPE)
return; return;
}
/* /*
* If this isn't a sequence, index, or composite type then it's * If this isn't a sequence then it's possibly going to have
* possibly going to have columns associated with it that might have * column-level ACLs associated with it.
* ACLs.
*/ */
if (pg_class_tuple->relkind != RELKIND_SEQUENCE) if (pg_class_tuple->relkind != RELKIND_SEQUENCE)
{ {
@ -5724,6 +5727,11 @@ recordExtObjInitPriv(Oid objoid, Oid classoid)
SysScanDesc scan; SysScanDesc scan;
Relation relation; Relation relation;
/*
* Note: this is dead code, given that we don't allow large objects to
* be made extension members. But it seems worth carrying in case
* some future caller of this function has need for it.
*/
relation = table_open(LargeObjectMetadataRelationId, RowExclusiveLock); relation = table_open(LargeObjectMetadataRelationId, RowExclusiveLock);
/* There's no syscache for pg_largeobject_metadata */ /* There's no syscache for pg_largeobject_metadata */
@ -5866,19 +5874,22 @@ removeExtObjInitPriv(Oid objoid, Oid classoid)
elog(ERROR, "cache lookup failed for relation %u", objoid); elog(ERROR, "cache lookup failed for relation %u", objoid);
pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple); pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple);
/* Indexes don't have permissions */ /*
* Indexes don't have permissions, neither do the pg_class rows for
* composite types. (These cases are unreachable given the
* restrictions in ALTER EXTENSION DROP, but let's check anyway.)
*/
if (pg_class_tuple->relkind == RELKIND_INDEX || if (pg_class_tuple->relkind == RELKIND_INDEX ||
pg_class_tuple->relkind == RELKIND_PARTITIONED_INDEX) pg_class_tuple->relkind == RELKIND_PARTITIONED_INDEX ||
return; pg_class_tuple->relkind == RELKIND_COMPOSITE_TYPE)
{
/* Composite types don't have permissions either */ ReleaseSysCache(tuple);
if (pg_class_tuple->relkind == RELKIND_COMPOSITE_TYPE)
return; return;
}
/* /*
* If this isn't a sequence, index, or composite type then it's * If this isn't a sequence then it's possibly going to have
* possibly going to have columns associated with it that might have * column-level ACLs associated with it.
* ACLs.
*/ */
if (pg_class_tuple->relkind != RELKIND_SEQUENCE) if (pg_class_tuple->relkind != RELKIND_SEQUENCE)
{ {

View File

@ -1,2 +1,4 @@
test_pg_dump is an extension explicitly to test pg_dump when test_pg_dump is an extension explicitly to test pg_dump when
extensions are present in the system. extensions are present in the system.
We also make use of this module to test ALTER EXTENSION ADD/DROP.

View File

@ -4,7 +4,8 @@ ALTER EXTENSION test_pg_dump ADD DATABASE postgres; -- error
ERROR: syntax error at or near "DATABASE" ERROR: syntax error at or near "DATABASE"
LINE 1: ALTER EXTENSION test_pg_dump ADD DATABASE postgres; LINE 1: ALTER EXTENSION test_pg_dump ADD DATABASE postgres;
^ ^
CREATE TABLE test_pg_dump_t1 (c1 int); CREATE TABLE test_pg_dump_t1 (c1 int, junk text);
ALTER TABLE test_pg_dump_t1 DROP COLUMN junk; -- to exercise dropped-col cases
CREATE VIEW test_pg_dump_v1 AS SELECT * FROM test_pg_dump_t1; CREATE VIEW test_pg_dump_v1 AS SELECT * FROM test_pg_dump_t1;
CREATE MATERIALIZED VIEW test_pg_dump_mv1 AS SELECT * FROM test_pg_dump_t1; CREATE MATERIALIZED VIEW test_pg_dump_mv1 AS SELECT * FROM test_pg_dump_t1;
CREATE SCHEMA test_pg_dump_s1; CREATE SCHEMA test_pg_dump_s1;

View File

@ -3,7 +3,8 @@ CREATE EXTENSION test_pg_dump;
ALTER EXTENSION test_pg_dump ADD DATABASE postgres; -- error ALTER EXTENSION test_pg_dump ADD DATABASE postgres; -- error
CREATE TABLE test_pg_dump_t1 (c1 int); CREATE TABLE test_pg_dump_t1 (c1 int, junk text);
ALTER TABLE test_pg_dump_t1 DROP COLUMN junk; -- to exercise dropped-col cases
CREATE VIEW test_pg_dump_v1 AS SELECT * FROM test_pg_dump_t1; CREATE VIEW test_pg_dump_v1 AS SELECT * FROM test_pg_dump_t1;
CREATE MATERIALIZED VIEW test_pg_dump_mv1 AS SELECT * FROM test_pg_dump_t1; CREATE MATERIALIZED VIEW test_pg_dump_mv1 AS SELECT * FROM test_pg_dump_t1;
CREATE SCHEMA test_pg_dump_s1; CREATE SCHEMA test_pg_dump_s1;