This patch seems to address all the problems with usernames with double
quotes in them. The only thing I'm worried about is what happens when you
run pg_dump now against old versions of postgres that don't use the new
quoting rules...
I've done lots of dumping and loading with usernames like [\,"- _ *<> '\,\
\" \' = \" -%,*&^% and I haven't managed to break it yet. However, whomever
commits this patch should check my logic carefully, and especially check
that I have allowed properly for malloc() space for the extra characters and
stuff.
Cheers,
Chris
? src/Makefile.global
? src/backend/postgres
? src/backend/access/common/.deps
? src/backend/access/gist/.deps
? src/backend/access/hash/.deps
? src/backend/access/heap/.deps
? src/backend/access/index/.deps
? src/backend/access/nbtree/.deps
? src/backend/access/rtree/.deps
? src/backend/access/transam/.deps
? src/backend/bootstrap/.deps
? src/backend/catalog/.deps
? src/backend/catalog/postgres.bki
? src/backend/catalog/postgres.description
? src/backend/commands/.deps
? src/backend/executor/.deps
? src/backend/lib/.deps
? src/backend/libpq/.deps
? src/backend/main/.deps
? src/backend/nodes/.deps
? src/backend/optimizer/geqo/.deps
? src/backend/optimizer/path/.deps
? src/backend/optimizer/plan/.deps
? src/backend/optimizer/prep/.deps
? src/backend/optimizer/util/.deps
? src/backend/parser/.deps
? src/backend/parser/bison.core
? src/backend/port/.deps
? src/backend/postmaster/.deps
? src/backend/regex/.deps
? src/backend/rewrite/.deps
? src/backend/storage/buffer/.deps
? src/backend/storage/file/.deps
? src/backend/storage/freespace/.deps
? src/backend/storage/ipc/.deps
? src/backend/storage/large_object/.deps
? src/backend/storage/lmgr/.deps
? src/backend/storage/page/.deps
? src/backend/storage/smgr/.deps
? src/backend/tcop/.deps
? src/backend/utils/.deps
? src/backend/utils/adt/.deps
? src/backend/utils/cache/.deps
? src/backend/utils/error/.deps
? src/backend/utils/fmgr/.deps
? src/backend/utils/hash/.deps
? src/backend/utils/init/.deps
? src/backend/utils/mb/.deps
? src/backend/utils/mb/conversion_procs/conversion_create.sql
? src/backend/utils/mb/conversion_procs/ascii_and_mic/.deps
? src/backend/utils/mb/conversion_procs/ascii_and_mic/libascii_and_mic.so.0
? src/backend/utils/mb/conversion_procs/cyrillic_and_mic/.deps
? src/backend/utils/mb/conversion_procs/cyrillic_and_mic/libcyrillic_and_mic.so.0
? src/backend/utils/mb/conversion_procs/euc_cn_and_mic/.deps
? src/backend/utils/mb/conversion_procs/euc_cn_and_mic/libeuc_cn_and_mic.so.0
? src/backend/utils/mb/conversion_procs/euc_jp_and_sjis/.deps
? src/backend/utils/mb/conversion_procs/euc_jp_and_sjis/libeuc_jp_and_sjis.so.0
? src/backend/utils/mb/conversion_procs/euc_kr_and_mic/.deps
? src/backend/utils/mb/conversion_procs/euc_kr_and_mic/libeuc_kr_and_mic.so.0
? src/backend/utils/mb/conversion_procs/euc_tw_and_big5/.deps
? src/backend/utils/mb/conversion_procs/euc_tw_and_big5/libeuc_tw_and_big5.so.0
? src/backend/utils/mb/conversion_procs/latin2_and_win1250/.deps
? src/backend/utils/mb/conversion_procs/latin2_and_win1250/liblatin2_and_win1250.so.0
? src/backend/utils/mb/conversion_procs/latin_and_mic/.deps
? src/backend/utils/mb/conversion_procs/latin_and_mic/liblatin_and_mic.so.0
? src/backend/utils/mb/conversion_procs/utf8_and_ascii/.deps
? src/backend/utils/mb/conversion_procs/utf8_and_ascii/libutf8_and_ascii.so.0
? src/backend/utils/mb/conversion_procs/utf8_and_big5/.deps
? src/backend/utils/mb/conversion_procs/utf8_and_big5/libutf8_and_big5.so.0
? src/backend/utils/mb/conversion_procs/utf8_and_cyrillic/.deps
? src/backend/utils/mb/conversion_procs/utf8_and_cyrillic/libutf8_and_cyrillic.so.0
? src/backend/utils/mb/conversion_procs/utf8_and_euc_cn/.deps
? src/backend/utils/mb/conversion_procs/utf8_and_euc_cn/libutf8_and_euc_cn.so.0
? src/backend/utils/mb/conversion_procs/utf8_and_euc_jp/.deps
? src/backend/utils/mb/conversion_procs/utf8_and_euc_jp/libutf8_and_euc_jp.so.0
? src/backend/utils/mb/conversion_procs/utf8_and_euc_kr/.deps
? src/backend/utils/mb/conversion_procs/utf8_and_euc_kr/libutf8_and_euc_kr.so.0
? src/backend/utils/mb/conversion_procs/utf8_and_euc_tw/.deps
? src/backend/utils/mb/conversion_procs/utf8_and_euc_tw/libutf8_and_euc_tw.so.0
? src/backend/utils/mb/conversion_procs/utf8_and_gb18030/.deps
? src/backend/utils/mb/conversion_procs/utf8_and_gb18030/libutf8_and_gb18030.so.0
? src/backend/utils/mb/conversion_procs/utf8_and_gbk/.deps
? src/backend/utils/mb/conversion_procs/utf8_and_gbk/libutf8_and_gbk.so.0
? src/backend/utils/mb/conversion_procs/utf8_and_iso8859/.deps
? src/backend/utils/mb/conversion_procs/utf8_and_iso8859/libutf8_and_iso8859.so.0
? src/backend/utils/mb/conversion_procs/utf8_and_iso8859_1/.deps
? src/backend/utils/mb/conversion_procs/utf8_and_iso8859_1/libutf8_and_iso8859_1.so.0
? src/backend/utils/mb/conversion_procs/utf8_and_johab/.deps
? src/backend/utils/mb/conversion_procs/utf8_and_johab/libutf8_and_johab.so.0
? src/backend/utils/mb/conversion_procs/utf8_and_sjis/.deps
? src/backend/utils/mb/conversion_procs/utf8_and_sjis/libutf8_and_sjis.so.0
? src/backend/utils/mb/conversion_procs/utf8_and_tcvn/.deps
? src/backend/utils/mb/conversion_procs/utf8_and_tcvn/libutf8_and_tcvn.so.0
? src/backend/utils/mb/conversion_procs/utf8_and_uhc/.deps
? src/backend/utils/mb/conversion_procs/utf8_and_uhc/libutf8_and_uhc.so.0
? src/backend/utils/mb/conversion_procs/utf8_and_win1250/.deps
? src/backend/utils/mb/conversion_procs/utf8_and_win1250/libutf8_and_win1250.so.0
? src/backend/utils/mb/conversion_procs/utf8_and_win1256/.deps
? src/backend/utils/mb/conversion_procs/utf8_and_win1256/libutf8_and_win1256.so.0
? src/backend/utils/mb/conversion_procs/utf8_and_win874/.deps
? src/backend/utils/mb/conversion_procs/utf8_and_win874/libutf8_and_win874.so.0
? src/backend/utils/misc/.deps
? src/backend/utils/mmgr/.deps
? src/backend/utils/sort/.deps
? src/backend/utils/time/.deps
? src/bin/initdb/initdb
? src/bin/initlocation/initlocation
? src/bin/ipcclean/ipcclean
? src/bin/pg_config/pg_config
? src/bin/pg_controldata/.deps
? src/bin/pg_controldata/pg_controldata
? src/bin/pg_ctl/pg_ctl
? src/bin/pg_dump/.deps
? src/bin/pg_dump/pg_dump
? src/bin/pg_dump/pg_dumpall
? src/bin/pg_dump/pg_restore
? src/bin/pg_encoding/.deps
? src/bin/pg_encoding/pg_encoding
? src/bin/pg_id/.deps
? src/bin/pg_id/pg_id
? src/bin/pg_resetxlog/.deps
? src/bin/pg_resetxlog/pg_resetxlog
? src/bin/psql/.deps
? src/bin/psql/psql
? src/bin/scripts/.deps
? src/bin/scripts/clusterdb
? src/bin/scripts/createdb
? src/bin/scripts/createlang
? src/bin/scripts/createuser
? src/bin/scripts/dropdb
? src/bin/scripts/droplang
? src/bin/scripts/dropuser
? src/bin/scripts/vacuumdb
? src/include/pg_config.h
? src/include/stamp-h
? src/interfaces/ecpg/compatlib/.deps
? src/interfaces/ecpg/compatlib/libecpg_compat.so.1
? src/interfaces/ecpg/ecpglib/.deps
? src/interfaces/ecpg/ecpglib/libecpg.so.4
? src/interfaces/ecpg/pgtypeslib/.deps
? src/interfaces/ecpg/pgtypeslib/libpgtypes.so.1
? src/interfaces/ecpg/preproc/.deps
? src/interfaces/ecpg/preproc/ecpg
? src/interfaces/libpq/.deps
? src/interfaces/libpq/libpq.so.3
? src/pl/plpgsql/src/.deps
? src/pl/plpgsql/src/libplpgsql.so.1
? src/pl/plpgsql/src/pl_exec.c.working
? src/port/.deps
? src/test/regress/.deps
? src/test/regress/log
? src/test/regress/pg_regress
? src/test/regress/results
? src/test/regress/tmp_check
? src/test/regress/expected/constraints.out
? src/test/regress/expected/copy.out
? src/test/regress/expected/create_function_1.out
? src/test/regress/expected/create_function_2.out
? src/test/regress/expected/misc.out
? src/test/regress/sql/constraints.sql
? src/test/regress/sql/copy.sql
? src/test/regress/sql/create_function_1.sql
? src/test/regress/sql/create_function_2.sql
? src/test/regress/sql/misc.sql
Index: src/backend/utils/adt/acl.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/backend/utils/adt/acl.c,v
retrieving revision 1.94
diff -c -r1.94 acl.c
*** src/backend/utils/adt/acl.c 4 Aug 2003 02:40:04 -0000 1.94
--- src/backend/utils/adt/acl.c 11 Aug 2003 04:18:27 -0000
***************
*** 61,68 ****
* RETURNS:
* the string position in 's' that points to the next non-space character
* in 's', after any quotes. Also:
! * - loads the identifier into 'name'. (If no identifier is found, 'name'
! * contains an empty string.) name must be NAMEDATALEN bytes.
*/
static const char *
getid(const char *s, char *n)
--- 61,68 ----
* RETURNS:
* the string position in 's' that points to the next non-space character
* in 's', after any quotes. Also:
! * - loads the identifier into 'n'. (If no identifier is found, 'n'
! * contains an empty string.) 'n' must be NAMEDATALEN bytes.
*/
static const char *
getid(const char *s, char *n)
***************
*** 83,89 ****
in_quotes);
s++)
{
! if (*s == '"')
in_quotes = !in_quotes;
else
{
--- 83,90 ----
in_quotes);
s++)
{
! /* This shouldn't overflow as there will always be the NULL terminator
*/
! if (*s == '"' && *(s + 1) != '"')
in_quotes = !in_quotes;
else
{
***************
*** 94,99 ****
--- 95,104 ----
errdetail("Identifier must be less than %d
characters.",
NAMEDATALEN)));
+ /* If we've hit an escaped double quote (""), then skip the
escaping char */
+ if (*s == '"' && *(s + 1) == '"') s++;
+
+ /* Add the character to the string */
n[len++] = *s;
}
}
***************
*** 105,111 ****
/*
* Write a user or group Name at *p, surrounding it with double quotes if
! * needed. There must be at least NAMEDATALEN+2 bytes available at *p.
*/
static void
putid(char *p, const char *s)
--- 110,117 ----
/*
* Write a user or group Name at *p, surrounding it with double quotes if
! * needed. 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
putid(char *p, const char *s)
***************
*** 124,131 ****
}
if (!safe)
*p++ = '"';
! for (src = s; *src; src++)
*p++ = *src;
if (!safe)
*p++ = '"';
*p = '\0';
--- 130,141 ----
}
if (!safe)
*p++ = '"';
! for (src = s; *src; src++) {
! /* A double quote character in a username is encoded as "" */
! if (!safe && *src == '"')
! *p++ = '"';
*p++ = *src;
+ }
if (!safe)
*p++ = '"';
*p = '\0';
***************
*** 358,364 ****
out = palloc(strlen("group =/") +
2 * N_ACL_RIGHTS +
! 2 * (NAMEDATALEN + 2) +
1);
p = out;
--- 368,374 ----
out = palloc(strlen("group =/") +
2 * N_ACL_RIGHTS +
! 2 * (2 * NAMEDATALEN + 2) +
1);
p = out;
Index: src/bin/pg_dump/dumputils.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/bin/pg_dump/dumputils.c,v
retrieving revision 1.8
diff -c -r1.8 dumputils.c
*** src/bin/pg_dump/dumputils.c 4 Aug 2003 02:40:09 -0000 1.8
--- src/bin/pg_dump/dumputils.c 11 Aug 2003 04:18:28 -0000
***************
*** 557,579 ****
copyAclUserName(PQExpBuffer output, char *input)
{
resetPQExpBuffer(output);
while (*input && *input != '=')
{
if (*input != '"')
appendPQExpBufferChar(output, *input++);
else
{
input++;
! while (*input != '"')
{
if (*input == '\0')
return input; /* really a syntax
error... */
/*
! * There is no quoting convention here, thus we can't
cope
! * with usernames containing double quotes. Keep this
* code in sync with putid() in backend's acl.c.
*/
appendPQExpBufferChar(output, *input++);
}
input++;
--- 557,583 ----
copyAclUserName(PQExpBuffer output, char *input)
{
resetPQExpBuffer(output);
+
while (*input && *input != '=')
{
+ /* If user name isn't quoted, then just add it to the output buffer */
if (*input != '"')
appendPQExpBufferChar(output, *input++);
+ /* Otherwise, it's a quoted username */
else
{
input++;
! /* Loop until we come across an unescaped quote */
! while (!(*input == '"' && *(input + 1) != '"'))
{
if (*input == '\0')
return input; /* really a syntax
error... */
/*
! * Quoting convention is to escape " as "". Keep this
* code in sync with putid() in backend's acl.c.
*/
+ if (*input == '"' && *(input + 1) == '"') input++;
appendPQExpBufferChar(output, *input++);
}
input++;
---------------------------(end of broadcast)---------------------------
TIP 5: Have you checked our extensive FAQ?
http://www.postgresql.org/docs/faqs/FAQ.html