fix-ACL-quoting-logic.patch
text/x-diff
Filename: fix-ACL-quoting-logic.patch
Type: text/x-diff
Part: 0
Patch
Format: unified
| File | + | − |
|---|---|---|
| src/backend/utils/adt/acl.c | 18 | 6 |
diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c
index ca3c5ee3df3..bd2435198e1 100644
--- a/src/backend/utils/adt/acl.c
+++ b/src/backend/utils/adt/acl.c
@@ -134,6 +134,16 @@ static AclResult pg_role_aclcheck(Oid role_oid, Oid roleid, AclMode mode);
static void RoleMembershipCacheCallback(Datum arg, int cacheid, uint32 hashvalue);
+/*
+ * Test whether an identifier char can be left unquoted in ACLs
+ */
+static inline bool
+is_safe_acl_char(unsigned char c)
+{
+ /* We don't trust isalnum() to deliver consistent results for non-ASCII */
+ return IS_HIGHBIT_SET(c) || isalnum(c) || c == '_';
+}
+
/*
* getid
* Consumes the first alphanumeric string (identifier) found in string
@@ -162,18 +172,20 @@ getid(const char *s, char *n, Node *escontext)
/* This code had better match what putid() does, below */
for (;
*s != '\0' &&
- (isalnum((unsigned char) *s) ||
- *s == '_' ||
- *s == '"' ||
- in_quotes);
+ (in_quotes || is_safe_acl_char(*s) || *s == '"');
s++)
{
if (*s == '"')
{
+ if (!in_quotes)
+ {
+ in_quotes = true;
+ continue;
+ }
/* safe to look at next char (could be '\0' though) */
if (*(s + 1) != '"')
{
- in_quotes = !in_quotes;
+ in_quotes = false;
continue;
}
/* it's an escaped double quote; skip the escaping char */
@@ -210,7 +222,7 @@ putid(char *p, const char *s)
for (src = s; *src; src++)
{
/* This test had better match what getid() does, above */
- if (!isalnum((unsigned char) *src) && *src != '_')
+ if (!is_safe_acl_char(*src))
{
safe = false;
break;