aboutsummaryrefslogtreecommitdiff
path: root/src/bin/pg_dump/dumputils.c
diff options
context:
space:
mode:
authorNoah Misch <noah@leadboat.com>2021-01-16 12:21:35 -0800
committerNoah Misch <noah@leadboat.com>2021-01-16 12:21:39 -0800
commita0d31b1c94143c12c98da85652aeb5ff240489c7 (patch)
tree07ba7ad1b8f9d5c3b8c69b7f1994c2e0f3101052 /src/bin/pg_dump/dumputils.c
parent66087f7e922c7279ee2c1967760de0c1f942522b (diff)
downloadpostgresql-a0d31b1c94143c12c98da85652aeb5ff240489c7.tar.gz
postgresql-a0d31b1c94143c12c98da85652aeb5ff240489c7.zip
Fix pg_dump for GRANT OPTION among initial privileges.
The context is an object that no longer bears some aclitem that it bore initially. (A user issued REVOKE or GRANT statements upon the object.) pg_dump is forming SQL to reproduce the object ACL. Since initdb creates no ACL bearing GRANT OPTION, reaching this bug requires an extension where the creation script establishes such an ACL. No PGXN extension does that. If an installation did reach the bug, pg_dump would have omitted a semicolon, causing a REVOKE and the next SQL statement to fail. Separately, since the affected code exists to eliminate an entire aclitem, it wants plain REVOKE, not REVOKE GRANT OPTION FOR. Back-patch to 9.6, where commit 23f34fa4ba358671adab16773e79c17c92cbc870 first appeared. Discussion: https://postgr.es/m/20210109102423.GA160022@rfd.leadboat.com
Diffstat (limited to 'src/bin/pg_dump/dumputils.c')
-rw-r--r--src/bin/pg_dump/dumputils.c61
1 files changed, 22 insertions, 39 deletions
diff --git a/src/bin/pg_dump/dumputils.c b/src/bin/pg_dump/dumputils.c
index ef8b53cd091..1ef836500fd 100644
--- a/src/bin/pg_dump/dumputils.c
+++ b/src/bin/pg_dump/dumputils.c
@@ -168,48 +168,28 @@ buildACLCommands(const char *name, const char *subname, const char *nspname,
for (i = 0; i < nraclitems; i++)
{
if (!parseAclItem(raclitems[i], type, name, subname, remoteVersion,
- grantee, grantor, privs, privswgo))
+ grantee, grantor, privs, NULL))
{
ok = false;
break;
}
- if (privs->len > 0 || privswgo->len > 0)
+ if (privs->len > 0)
{
- if (privs->len > 0)
- {
- appendPQExpBuffer(firstsql, "%sREVOKE %s ON %s ",
- prefix, privs->data, type);
- if (nspname && *nspname)
- appendPQExpBuffer(firstsql, "%s.", fmtId(nspname));
- appendPQExpBuffer(firstsql, "%s FROM ", name);
- if (grantee->len == 0)
- appendPQExpBufferStr(firstsql, "PUBLIC;\n");
- else if (strncmp(grantee->data, "group ",
- strlen("group ")) == 0)
- appendPQExpBuffer(firstsql, "GROUP %s;\n",
- fmtId(grantee->data + strlen("group ")));
- else
- appendPQExpBuffer(firstsql, "%s;\n",
- fmtId(grantee->data));
- }
- if (privswgo->len > 0)
- {
- appendPQExpBuffer(firstsql,
- "%sREVOKE GRANT OPTION FOR %s ON %s ",
- prefix, privswgo->data, type);
- if (nspname && *nspname)
- appendPQExpBuffer(firstsql, "%s.", fmtId(nspname));
- appendPQExpBuffer(firstsql, "%s FROM ", name);
- if (grantee->len == 0)
- appendPQExpBufferStr(firstsql, "PUBLIC");
- else if (strncmp(grantee->data, "group ",
- strlen("group ")) == 0)
- appendPQExpBuffer(firstsql, "GROUP %s",
- fmtId(grantee->data + strlen("group ")));
- else
- appendPQExpBufferStr(firstsql, fmtId(grantee->data));
- }
+ appendPQExpBuffer(firstsql, "%sREVOKE %s ON %s ",
+ prefix, privs->data, type);
+ if (nspname && *nspname)
+ appendPQExpBuffer(firstsql, "%s.", fmtId(nspname));
+ appendPQExpBuffer(firstsql, "%s FROM ", name);
+ if (grantee->len == 0)
+ appendPQExpBufferStr(firstsql, "PUBLIC;\n");
+ else if (strncmp(grantee->data, "group ",
+ strlen("group ")) == 0)
+ appendPQExpBuffer(firstsql, "GROUP %s;\n",
+ fmtId(grantee->data + strlen("group ")));
+ else
+ appendPQExpBuffer(firstsql, "%s;\n",
+ fmtId(grantee->data));
}
}
}
@@ -462,8 +442,11 @@ buildDefaultACLCommands(const char *type, const char *nspname,
* The returned grantee string will be the dequoted username or groupname
* (preceded with "group " in the latter case). Note that a grant to PUBLIC
* is represented by an empty grantee string. The returned grantor is the
- * dequoted grantor name. Privilege characters are decoded and split between
- * privileges with grant option (privswgo) and without (privs).
+ * dequoted grantor name. Privilege characters are translated to GRANT/REVOKE
+ * comma-separated privileges lists. If "privswgo" is non-NULL, the result is
+ * separate lists for privileges with grant option ("privswgo") and without
+ * ("privs"). Otherwise, "privs" bears every relevant privilege, ignoring the
+ * grant option distinction.
*
* Note: for cross-version compatibility, it's important to use ALL to
* represent the privilege sets whenever appropriate.
@@ -514,7 +497,7 @@ parseAclItem(const char *item, const char *type,
do { \
if ((pos = strchr(eqpos + 1, code))) \
{ \
- if (*(pos + 1) == '*') \
+ if (*(pos + 1) == '*' && privswgo != NULL) \
{ \
AddAcl(privswgo, keywd, subname); \
all_without_go = false; \