Skip to content

Commit 5302ff9

Browse files
committed
Fix pg_dumpall to cope with dangling OIDs in pg_auth_members.
There is a race condition between "GRANT role" and "DROP ROLE", which allows GRANT to install pg_auth_members entries that refer to dropped roles. (Commit 6566133 prevented that for the grantor field, but not for the granted or grantee roles.) We'll soon fix that, at least in HEAD, but pg_dumpall needs to cope with the situation in case of pre-existing inconsistency. As pg_dumpall stands, it will emit invalid commands like 'GRANT foo TO ""', which causes pg_upgrade to fail. Fix it to emit warnings and skip those GRANTs, instead. There was some discussion of removing the problem by changing dumpRoleMembership's query to use JOIN not LEFT JOIN, but that would result in silently ignoring such entries. It seems better to produce a warning. Pre-v16 branches already coped with dangling grantor OIDs by simply omitting the GRANTED BY clause. I left that behavior as-is, although it's somewhat inconsistent with the behavior of later branches. Reported-by: Virender Singla <virender.cse@gmail.com> Discussion: https://postgr.es/m/CAM6Zo8woa62ZFHtMKox6a4jb8qQ=w87R2L0K8347iE-juQL2EA@mail.gmail.com Backpatch-through: 13
1 parent bc01859 commit 5302ff9

File tree

1 file changed

+28
-6
lines changed

1 file changed

+28
-6
lines changed

src/bin/pg_dump/pg_dumpall.c

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1002,10 +1002,12 @@ dumpRoleMembership(PGconn *conn)
10021002
PGresult *res;
10031003
int i;
10041004

1005-
printfPQExpBuffer(buf, "SELECT ur.rolname AS roleid, "
1005+
printfPQExpBuffer(buf, "SELECT ur.rolname AS role, "
10061006
"um.rolname AS member, "
10071007
"a.admin_option, "
1008-
"ug.rolname AS grantor "
1008+
"ug.rolname AS grantor, "
1009+
"a.roleid AS roleid, "
1010+
"a.member AS memberid "
10091011
"FROM pg_auth_members a "
10101012
"LEFT JOIN %s ur on ur.oid = a.roleid "
10111013
"LEFT JOIN %s um on um.oid = a.member "
@@ -1019,13 +1021,33 @@ dumpRoleMembership(PGconn *conn)
10191021

10201022
for (i = 0; i < PQntuples(res); i++)
10211023
{
1022-
char *roleid = PQgetvalue(res, i, 0);
1024+
char *role = PQgetvalue(res, i, 0);
10231025
char *member = PQgetvalue(res, i, 1);
1024-
char *option = PQgetvalue(res, i, 2);
1026+
char *admin_option = PQgetvalue(res, i, 2);
10251027

1026-
fprintf(OPF, "GRANT %s", fmtId(roleid));
1028+
/*
1029+
* Due to race conditions, the role and/or member could have been
1030+
* dropped. If we find such cases, print a warning and skip the
1031+
* entry.
1032+
*/
1033+
if (PQgetisnull(res, i, 0))
1034+
{
1035+
/* translator: %s represents a numeric role OID */
1036+
pg_log_warning("found orphaned pg_auth_members entry for role %s",
1037+
PQgetvalue(res, i, 4));
1038+
continue;
1039+
}
1040+
if (PQgetisnull(res, i, 1))
1041+
{
1042+
/* translator: %s represents a numeric role OID */
1043+
pg_log_warning("found orphaned pg_auth_members entry for role %s",
1044+
PQgetvalue(res, i, 5));
1045+
continue;
1046+
}
1047+
1048+
fprintf(OPF, "GRANT %s", fmtId(role));
10271049
fprintf(OPF, " TO %s", fmtId(member));
1028-
if (*option == 't')
1050+
if (*admin_option == 't')
10291051
fprintf(OPF, " WITH ADMIN OPTION");
10301052

10311053
/*

0 commit comments

Comments
 (0)