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

Reply via email to