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 */
6767static const char *
6868getid (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 */
110119static void
111120putid (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 ;
0 commit comments