Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 2b5f049

Browse files
committed
Handle double-quotes correctly in user names in ACL lists.
Christopher Kings-Lynne
1 parent 8e97f45 commit 2b5f049

File tree

2 files changed

+40
-21
lines changed

2 files changed

+40
-21
lines changed

src/backend/utils/adt/acl.c

+31-17
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.94 2003/08/04 02:40:04 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.95 2003/08/14 14:19:07 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -61,8 +61,8 @@ static AclMode convert_schema_priv_string(text *priv_type_text);
6161
* RETURNS:
6262
* the string position in 's' that points to the next non-space character
6363
* in 's', after any quotes. Also:
64-
* - loads the identifier into 'name'. (If no identifier is found, 'name'
65-
* contains an empty string.) name must be NAMEDATALEN bytes.
64+
* - loads the identifier into 'n'. (If no identifier is found, 'n'
65+
* contains an empty string.) 'n' must be NAMEDATALEN bytes.
6666
*/
6767
static const char *
6868
getid(const char *s, char *n)
@@ -74,7 +74,7 @@ getid(const char *s, char *n)
7474

7575
while (isspace((unsigned char) *s))
7676
s++;
77-
/* This test had better match what putid() does, below */
77+
/* This code had better match what putid() does, below */
7878
for (;
7979
*s != '\0' &&
8080
(isalnum((unsigned char) *s) ||
@@ -84,18 +84,26 @@ getid(const char *s, char *n)
8484
s++)
8585
{
8686
if (*s == '"')
87-
in_quotes = !in_quotes;
88-
else
8987
{
90-
if (len >= NAMEDATALEN - 1)
91-
ereport(ERROR,
92-
(errcode(ERRCODE_NAME_TOO_LONG),
93-
errmsg("identifier too long"),
94-
errdetail("Identifier must be less than %d characters.",
95-
NAMEDATALEN)));
96-
97-
n[len++] = *s;
88+
/* safe to look at next char (could be '\0' though) */
89+
if (*(s + 1) != '"')
90+
{
91+
in_quotes = !in_quotes;
92+
continue;
93+
}
94+
/* it's an escaped double quote; skip the escaping char */
95+
s++;
9896
}
97+
98+
/* Add the character to the string */
99+
if (len >= NAMEDATALEN - 1)
100+
ereport(ERROR,
101+
(errcode(ERRCODE_NAME_TOO_LONG),
102+
errmsg("identifier too long"),
103+
errdetail("Identifier must be less than %d characters.",
104+
NAMEDATALEN)));
105+
106+
n[len++] = *s;
99107
}
100108
n[len] = '\0';
101109
while (isspace((unsigned char) *s))
@@ -104,8 +112,9 @@ getid(const char *s, char *n)
104112
}
105113

106114
/*
107-
* Write a user or group Name at *p, surrounding it with double quotes if
108-
* needed. There must be at least NAMEDATALEN+2 bytes available at *p.
115+
* Write a user or group Name at *p, adding double quotes if needed.
116+
* There must be at least (2*NAMEDATALEN)+2 bytes available at *p.
117+
* This needs to be kept in sync with copyAclUserName in pg_dump/dumputils.c
109118
*/
110119
static void
111120
putid(char *p, const char *s)
@@ -125,7 +134,12 @@ putid(char *p, const char *s)
125134
if (!safe)
126135
*p++ = '"';
127136
for (src = s; *src; src++)
137+
{
138+
/* A double quote character in a username is encoded as "" */
139+
if (*src == '"')
140+
*p++ = '"';
128141
*p++ = *src;
142+
}
129143
if (!safe)
130144
*p++ = '"';
131145
*p = '\0';
@@ -358,7 +372,7 @@ aclitemout(PG_FUNCTION_ARGS)
358372

359373
out = palloc(strlen("group =/") +
360374
2 * N_ACL_RIGHTS +
361-
2 * (NAMEDATALEN + 2) +
375+
2 * (2 * NAMEDATALEN + 2) +
362376
1);
363377

364378
p = out;

src/bin/pg_dump/dumputils.c

+9-4
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $Header: /cvsroot/pgsql/src/bin/pg_dump/dumputils.c,v 1.8 2003/08/04 02:40:09 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/bin/pg_dump/dumputils.c,v 1.9 2003/08/14 14:19:11 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -557,23 +557,28 @@ static char *
557557
copyAclUserName(PQExpBuffer output, char *input)
558558
{
559559
resetPQExpBuffer(output);
560+
560561
while (*input && *input != '=')
561562
{
563+
/* If user name isn't quoted, then just add it to the output buffer */
562564
if (*input != '"')
563565
appendPQExpBufferChar(output, *input++);
564566
else
565567
{
568+
/* Otherwise, it's a quoted username */
566569
input++;
567-
while (*input != '"')
570+
/* Loop until we come across an unescaped quote */
571+
while (!(*input == '"' && *(input + 1) != '"'))
568572
{
569573
if (*input == '\0')
570574
return input; /* really a syntax error... */
571575

572576
/*
573-
* There is no quoting convention here, thus we can't cope
574-
* with usernames containing double quotes. Keep this
577+
* Quoting convention is to escape " as "". Keep this
575578
* code in sync with putid() in backend's acl.c.
576579
*/
580+
if (*input == '"' && *(input + 1) == '"')
581+
input++;
577582
appendPQExpBufferChar(output, *input++);
578583
}
579584
input++;

0 commit comments

Comments
 (0)