From f435cd1d385859a0cdb1d70fccc21dde2b1ee116 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 9afbab4b07..a6e6a0fa9a 100644 --- a/src/bin/pg_dump/pg_dumpall.c +++ b/src/bin/pg_dump/pg_dumpall.c @@ -50,6 +50,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 void buildShSecLabels(PGconn *conn, const char *catalog_name, @@ -1629,6 +1630,7 @@ dumpDatabases(PGconn *conn) static int runPgDump(const char *dbname) { + PQExpBuffer connstr = createPQExpBuffer(); PQExpBuffer cmd = createPQExpBuffer(); int ret; @@ -1644,7 +1646,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); @@ -1657,6 +1669,7 @@ runPgDump(const char *dbname) ret = system(cmd->data); destroyPQExpBuffer(cmd); + destroyPQExpBuffer(connstr); return ret; } @@ -1896,6 +1909,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. -- 2.40.0