summaryrefslogtreecommitdiff
path: root/src/bin/initdb/initdb.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2018-04-17 19:53:50 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2018-04-17 19:53:50 -0400
commit55d26ff638f063fbccf57843f2c27f9795895a5c (patch)
treebb094186f374620288b702217f8c26280dc9f719 /src/bin/initdb/initdb.c
parent9ffcccdb958d38db5051bf64143330ff445a26cc (diff)
Rationalize handling of single and double quotes in bootstrap data.
Change things around so that proper quoting of values interpolated into the BKI data by initdb is the responsibility of initdb, not something we half-heartedly handle by putting double quotes into the raw BKI data. (Note: experimentation shows that it still doesn't work to put a double quote into the initial superuser username, but that's the fault of inadequate quoting while interpolating the name into SQL scripts; the BKI aspect of it works fine now.) Having done that, we can remove the special-case handling of values that look like "something" from genbki.pl, and instead teach it to escape double --- and single --- quotes properly. This removes the nowhere-documented need to treat those specially in the BKI source data; whatever you write will be passed through unchanged into the inserted data value, modulo Perl's rules about single-quoted strings. Add documentation explaining the (pre-existing) handling of backslashes in the BKI data. Per an earlier discussion with John Naylor. Discussion: https://postgr.es/m/CAJVSVGUNao=-Q2-vAN3PYcdF5tnL5JAHwGwzZGuYHtq+Mk_9ng@mail.gmail.com
Diffstat (limited to 'src/bin/initdb/initdb.c')
-rw-r--r--src/bin/initdb/initdb.c63
1 files changed, 59 insertions, 4 deletions
diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c
index 4907a379038..b39115c346d 100644
--- a/src/bin/initdb/initdb.c
+++ b/src/bin/initdb/initdb.c
@@ -265,6 +265,7 @@ static void make_postgres(FILE *cmdfd);
static void trapsig(int signum);
static void check_ok(void);
static char *escape_quotes(const char *src);
+static char *escape_quotes_bki(const char *src);
static int locale_date_order(const char *locale);
static void check_locale_name(int category, const char *locale,
char **canonname);
@@ -324,6 +325,10 @@ do { \
output_failed = true, output_errno = errno; \
} while (0)
+/*
+ * Escape single quotes and backslashes, suitably for insertions into
+ * configuration files or SQL E'' strings.
+ */
static char *
escape_quotes(const char *src)
{
@@ -338,6 +343,52 @@ escape_quotes(const char *src)
}
/*
+ * Escape a field value to be inserted into the BKI data.
+ * Here, we first run the value through escape_quotes (which
+ * will be inverted by the backend's scanstr() function) and
+ * then overlay special processing of double quotes, which
+ * bootscanner.l will only accept as data if converted to octal
+ * representation ("\042"). We always wrap the value in double
+ * quotes, even if that isn't strictly necessary.
+ */
+static char *
+escape_quotes_bki(const char *src)
+{
+ char *result;
+ char *data = escape_quotes(src);
+ char *resultp;
+ char *datap;
+ int nquotes = 0;
+
+ /* count double quotes in data */
+ datap = data;
+ while ((datap = strchr(datap, '"')) != NULL)
+ {
+ nquotes++;
+ datap++;
+ }
+
+ result = (char *) pg_malloc(strlen(data) + 3 + nquotes * 3);
+ resultp = result;
+ *resultp++ = '"';
+ for (datap = data; *datap; datap++)
+ {
+ if (*datap == '"')
+ {
+ strcpy(resultp, "\\042");
+ resultp += 4;
+ }
+ else
+ *resultp++ = *datap;
+ }
+ *resultp++ = '"';
+ *resultp = '\0';
+
+ free(data);
+ return result;
+}
+
+/*
* make a copy of the array of lines, with token replaced by replacement
* the first time it occurs on each line.
*
@@ -1368,13 +1419,17 @@ bootstrap_template1(void)
bki_lines = replace_token(bki_lines, "FLOAT8PASSBYVAL",
FLOAT8PASSBYVAL ? "true" : "false");
- bki_lines = replace_token(bki_lines, "POSTGRES", escape_quotes(username));
+ bki_lines = replace_token(bki_lines, "POSTGRES",
+ escape_quotes_bki(username));
- bki_lines = replace_token(bki_lines, "ENCODING", encodingid_to_string(encodingid));
+ bki_lines = replace_token(bki_lines, "ENCODING",
+ encodingid_to_string(encodingid));
- bki_lines = replace_token(bki_lines, "LC_COLLATE", escape_quotes(lc_collate));
+ bki_lines = replace_token(bki_lines, "LC_COLLATE",
+ escape_quotes_bki(lc_collate));
- bki_lines = replace_token(bki_lines, "LC_CTYPE", escape_quotes(lc_ctype));
+ bki_lines = replace_token(bki_lines, "LC_CTYPE",
+ escape_quotes_bki(lc_ctype));
/*
* Pass correct LC_xxx environment to bootstrap.