From 2aaa14d4218350756bc51ab623dbf1f43dbe3fc1 Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Wed, 20 Feb 2013 17:08:54 +0200 Subject: [PATCH] Fix pg_dumpall with database names containing = If a database name contained a '=' character, pg_dumpall failed. The problem was in the way pg_dumpall passes the database name to pg_dump on the command line. If it contained a '=' character, pg_dump would interpret it as a libpq connection string instead of a plain database name. To fix, pass the database name to pg_dump as a connection string, "dbname=foo", with the database name escaped if necessary. Back-patch to all supported branches. --- src/bin/pg_dump/pg_dumpall.c | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/src/bin/pg_dump/pg_dumpall.c b/src/bin/pg_dump/pg_dumpall.c index 454b95c106..9f9070c27b 100644 --- a/src/bin/pg_dump/pg_dumpall.c +++ b/src/bin/pg_dump/pg_dumpall.c @@ -48,6 +48,7 @@ static void makeAlterConfigCommand(PGconn *conn, const char *arrayitem, static void dumpDatabases(PGconn *conn); static void dumpTimestamp(char *msg); static void doShellQuoting(PQExpBuffer buf, const char *str); +static void doConnStrQuoting(PQExpBuffer buf, const char *str); static int runPgDump(const char *dbname); static PGconn *connectDatabase(const char *dbname, const char *pghost, const char *pgport, @@ -1485,6 +1486,7 @@ dumpDatabases(PGconn *conn) static int runPgDump(const char *dbname) { + PQExpBuffer connstr = createPQExpBuffer(); PQExpBuffer cmd = createPQExpBuffer(); int ret; @@ -1500,7 +1502,17 @@ runPgDump(const char *dbname) else appendPQExpBuffer(cmd, " -Fp "); - doShellQuoting(cmd, dbname); + /* + * Construct a connection string from the database name, like + * dbname=''. pg_dump would usually also accept the + * database name as is, but if it contains any = characters, it would + * incorrectly treat it as a connection string. + */ + appendPQExpBuffer(connstr, "dbname='"); + doConnStrQuoting(connstr, dbname); + appendPQExpBuffer(connstr, "'"); + + doShellQuoting(cmd, connstr->data); appendPQExpBuffer(cmd, "%s", SYSTEMQUOTE); @@ -1513,6 +1525,7 @@ runPgDump(const char *dbname) ret = system(cmd->data); destroyPQExpBuffer(cmd); + destroyPQExpBuffer(connstr); return ret; } @@ -1708,6 +1721,25 @@ dumpTimestamp(char *msg) } +/* + * Append the given string to the buffer, with suitable quoting for passing + * the string as a value, in a keyword/pair value in a libpq connection + * string + */ +static void +doConnStrQuoting(PQExpBuffer buf, const char *str) +{ + while (*str) + { + /* ' and \ must be escaped by to \' and \\ */ + if (*str == '\'' || *str == '\\') + appendPQExpBufferChar(buf, '\\'); + + appendPQExpBufferChar(buf, *str); + str++; + } +} + /* * Append the given string to the shell command being built in the buffer, * with suitable shell-style quoting.