提交 2b5f049f 编写于 作者: T Tom Lane

Handle double-quotes correctly in user names in ACL lists.

Christopher Kings-Lynne
上级 8e97f45f
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.94 2003/08/04 02:40:04 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.95 2003/08/14 14:19:07 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -61,8 +61,8 @@ static AclMode convert_schema_priv_string(text *priv_type_text); ...@@ -61,8 +61,8 @@ static AclMode convert_schema_priv_string(text *priv_type_text);
* RETURNS: * RETURNS:
* the string position in 's' that points to the next non-space character * the string position in 's' that points to the next non-space character
* in 's', after any quotes. Also: * in 's', after any quotes. Also:
* - loads the identifier into 'name'. (If no identifier is found, 'name' * - loads the identifier into 'n'. (If no identifier is found, 'n'
* contains an empty string.) name must be NAMEDATALEN bytes. * contains an empty string.) 'n' must be NAMEDATALEN bytes.
*/ */
static const char * static const char *
getid(const char *s, char *n) getid(const char *s, char *n)
...@@ -74,7 +74,7 @@ getid(const char *s, char *n) ...@@ -74,7 +74,7 @@ getid(const char *s, char *n)
while (isspace((unsigned char) *s)) while (isspace((unsigned char) *s))
s++; s++;
/* This test had better match what putid() does, below */ /* This code had better match what putid() does, below */
for (; for (;
*s != '\0' && *s != '\0' &&
(isalnum((unsigned char) *s) || (isalnum((unsigned char) *s) ||
...@@ -84,18 +84,26 @@ getid(const char *s, char *n) ...@@ -84,18 +84,26 @@ getid(const char *s, char *n)
s++) s++)
{ {
if (*s == '"') if (*s == '"')
in_quotes = !in_quotes;
else
{ {
if (len >= NAMEDATALEN - 1) /* safe to look at next char (could be '\0' though) */
ereport(ERROR, if (*(s + 1) != '"')
(errcode(ERRCODE_NAME_TOO_LONG), {
errmsg("identifier too long"), in_quotes = !in_quotes;
errdetail("Identifier must be less than %d characters.", continue;
NAMEDATALEN))); }
/* it's an escaped double quote; skip the escaping char */
n[len++] = *s; s++;
} }
/* Add the character to the string */
if (len >= NAMEDATALEN - 1)
ereport(ERROR,
(errcode(ERRCODE_NAME_TOO_LONG),
errmsg("identifier too long"),
errdetail("Identifier must be less than %d characters.",
NAMEDATALEN)));
n[len++] = *s;
} }
n[len] = '\0'; n[len] = '\0';
while (isspace((unsigned char) *s)) while (isspace((unsigned char) *s))
...@@ -104,8 +112,9 @@ getid(const char *s, char *n) ...@@ -104,8 +112,9 @@ getid(const char *s, char *n)
} }
/* /*
* Write a user or group Name at *p, surrounding it with double quotes if * Write a user or group Name at *p, adding double quotes if needed.
* needed. There must be at least NAMEDATALEN+2 bytes available at *p. * There must be at least (2*NAMEDATALEN)+2 bytes available at *p.
* This needs to be kept in sync with copyAclUserName in pg_dump/dumputils.c
*/ */
static void static void
putid(char *p, const char *s) putid(char *p, const char *s)
...@@ -125,7 +134,12 @@ putid(char *p, const char *s) ...@@ -125,7 +134,12 @@ putid(char *p, const char *s)
if (!safe) if (!safe)
*p++ = '"'; *p++ = '"';
for (src = s; *src; src++) for (src = s; *src; src++)
{
/* A double quote character in a username is encoded as "" */
if (*src == '"')
*p++ = '"';
*p++ = *src; *p++ = *src;
}
if (!safe) if (!safe)
*p++ = '"'; *p++ = '"';
*p = '\0'; *p = '\0';
...@@ -358,7 +372,7 @@ aclitemout(PG_FUNCTION_ARGS) ...@@ -358,7 +372,7 @@ aclitemout(PG_FUNCTION_ARGS)
out = palloc(strlen("group =/") + out = palloc(strlen("group =/") +
2 * N_ACL_RIGHTS + 2 * N_ACL_RIGHTS +
2 * (NAMEDATALEN + 2) + 2 * (2 * NAMEDATALEN + 2) +
1); 1);
p = out; p = out;
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Header: /cvsroot/pgsql/src/bin/pg_dump/dumputils.c,v 1.8 2003/08/04 02:40:09 momjian Exp $ * $Header: /cvsroot/pgsql/src/bin/pg_dump/dumputils.c,v 1.9 2003/08/14 14:19:11 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -557,23 +557,28 @@ static char * ...@@ -557,23 +557,28 @@ static char *
copyAclUserName(PQExpBuffer output, char *input) copyAclUserName(PQExpBuffer output, char *input)
{ {
resetPQExpBuffer(output); resetPQExpBuffer(output);
while (*input && *input != '=') while (*input && *input != '=')
{ {
/* If user name isn't quoted, then just add it to the output buffer */
if (*input != '"') if (*input != '"')
appendPQExpBufferChar(output, *input++); appendPQExpBufferChar(output, *input++);
else else
{ {
/* Otherwise, it's a quoted username */
input++; input++;
while (*input != '"') /* Loop until we come across an unescaped quote */
while (!(*input == '"' && *(input + 1) != '"'))
{ {
if (*input == '\0') if (*input == '\0')
return input; /* really a syntax error... */ return input; /* really a syntax error... */
/* /*
* There is no quoting convention here, thus we can't cope * Quoting convention is to escape " as "". Keep this
* with usernames containing double quotes. Keep this
* code in sync with putid() in backend's acl.c. * code in sync with putid() in backend's acl.c.
*/ */
if (*input == '"' && *(input + 1) == '"')
input++;
appendPQExpBufferChar(output, *input++); appendPQExpBufferChar(output, *input++);
} }
input++; input++;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册