diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/catalog/genbki.pl | 13 | ||||
-rw-r--r-- | src/bin/initdb/initdb.c | 63 | ||||
-rw-r--r-- | src/include/catalog/pg_authid.dat | 5 | ||||
-rw-r--r-- | src/include/catalog/pg_database.dat | 5 | ||||
-rw-r--r-- | src/include/catalog/pg_proc.dat | 12 |
5 files changed, 77 insertions, 21 deletions
diff --git a/src/backend/catalog/genbki.pl b/src/backend/catalog/genbki.pl index b750ec9f0ac..938686f0ca7 100644 --- a/src/backend/catalog/genbki.pl +++ b/src/backend/catalog/genbki.pl @@ -660,12 +660,19 @@ sub print_bki_insert # since that represents a NUL char in C code. $bki_value = '' if $bki_value eq '\0'; + # Handle single quotes by doubling them, and double quotes by + # converting them to octal escapes, because that's what the + # bootstrap scanner requires. We do not process backslashes + # specially; this allows escape-string-style backslash escapes + # to be used in catalog data. + $bki_value =~ s/'/''/g; + $bki_value =~ s/"/\\042/g; + # Quote value if needed. We need not quote values that satisfy # the "id" pattern in bootscanner.l, currently "[-A-Za-z0-9_]+". $bki_value = sprintf(qq'"%s"', $bki_value) - if $bki_value !~ /^"[^"]+"$/ - and ( length($bki_value) == 0 - or $bki_value =~ /[^-A-Za-z0-9_]/); + if length($bki_value) == 0 + or $bki_value =~ /[^-A-Za-z0-9_]/; push @bki_values, $bki_value; } 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. diff --git a/src/include/catalog/pg_authid.dat b/src/include/catalog/pg_authid.dat index 52f42595600..d8421b01627 100644 --- a/src/include/catalog/pg_authid.dat +++ b/src/include/catalog/pg_authid.dat @@ -12,14 +12,11 @@ [ -# POSTGRES will be replaced at initdb time with a user choice that might -# contain non-word characters, so we must double-quote it. - # The C code typically refers to these roles using the #define symbols, # so make sure every entry has an oid_symbol value. { oid => '10', oid_symbol => 'BOOTSTRAP_SUPERUSERID', - rolname => '"POSTGRES"', rolsuper => 't', rolinherit => 't', + rolname => 'POSTGRES', rolsuper => 't', rolinherit => 't', rolcreaterole => 't', rolcreatedb => 't', rolcanlogin => 't', rolreplication => 't', rolbypassrls => 't', rolconnlimit => '-1', rolpassword => '_null_', rolvaliduntil => '_null_' }, diff --git a/src/include/catalog/pg_database.dat b/src/include/catalog/pg_database.dat index 957ca8408a5..002075685cc 100644 --- a/src/include/catalog/pg_database.dat +++ b/src/include/catalog/pg_database.dat @@ -12,13 +12,10 @@ [ -# LC_COLLATE and LC_CTYPE will be replaced at initdb time with user choices -# that might contain non-word characters, so we must double-quote them. - { oid => '1', oid_symbol => 'TemplateDbOid', descr => 'default template for new databases', datname => 'template1', datdba => 'PGUID', encoding => 'ENCODING', - datcollate => '"LC_COLLATE"', datctype => '"LC_CTYPE"', datistemplate => 't', + datcollate => 'LC_COLLATE', datctype => 'LC_CTYPE', datistemplate => 't', datallowconn => 't', datconnlimit => '-1', datlastsysoid => '0', datfrozenxid => '0', datminmxid => '1', dattablespace => '1663', datacl => '_null_' }, diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index 3c56ef6abcc..9b53855236f 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -2417,7 +2417,7 @@ { oid => '1216', descr => 'get description for table column', proname => 'col_description', prolang => '14', procost => '100', provolatile => 's', prorettype => 'text', proargtypes => 'oid int4', - prosrc => 'select description from pg_catalog.pg_description where objoid = $1 and classoid = \'\'pg_catalog.pg_class\'\'::pg_catalog.regclass and objsubid = $2' }, + prosrc => 'select description from pg_catalog.pg_description where objoid = $1 and classoid = \'pg_catalog.pg_class\'::pg_catalog.regclass and objsubid = $2' }, { oid => '1993', descr => 'get description for object id and shared catalog name', proname => 'shobj_description', prolang => '14', procost => '100', @@ -3483,11 +3483,11 @@ { oid => '879', descr => 'left-pad string to length', proname => 'lpad', prolang => '14', prorettype => 'text', proargtypes => 'text int4', - prosrc => 'select pg_catalog.lpad($1, $2, \'\' \'\')' }, + prosrc => 'select pg_catalog.lpad($1, $2, \' \')' }, { oid => '880', descr => 'right-pad string to length', proname => 'rpad', prolang => '14', prorettype => 'text', proargtypes => 'text int4', - prosrc => 'select pg_catalog.rpad($1, $2, \'\' \'\')' }, + prosrc => 'select pg_catalog.rpad($1, $2, \' \')' }, { oid => '881', descr => 'trim spaces from left end of string', proname => 'ltrim', prorettype => 'text', proargtypes => 'text', prosrc => 'ltrim1' }, @@ -6930,7 +6930,7 @@ descr => 'disk space usage for the main fork of the specified table or index', proname => 'pg_relation_size', prolang => '14', provolatile => 'v', prorettype => 'int8', proargtypes => 'regclass', - prosrc => 'select pg_catalog.pg_relation_size($1, \'\'main\'\')' }, + prosrc => 'select pg_catalog.pg_relation_size($1, \'main\')' }, { oid => '2332', descr => 'disk space usage for the specified fork of a table or index', proname => 'pg_relation_size', provolatile => 'v', prorettype => 'int8', @@ -8168,7 +8168,7 @@ { oid => '2932', descr => 'evaluate XPath expression', proname => 'xpath', prolang => '14', prorettype => '_xml', proargtypes => 'text xml', - prosrc => 'select pg_catalog.xpath($1, $2, \'\'{}\'\'::pg_catalog.text[])' }, + prosrc => 'select pg_catalog.xpath($1, $2, \'{}\'::pg_catalog.text[])' }, { oid => '2614', descr => 'test XML value against XPath expression', proname => 'xmlexists', prorettype => 'bool', proargtypes => 'text xml', @@ -8181,7 +8181,7 @@ { oid => '3050', descr => 'test XML value against XPath expression', proname => 'xpath_exists', prolang => '14', prorettype => 'bool', proargtypes => 'text xml', - prosrc => 'select pg_catalog.xpath_exists($1, $2, \'\'{}\'\'::pg_catalog.text[])' }, + prosrc => 'select pg_catalog.xpath_exists($1, $2, \'{}\'::pg_catalog.text[])' }, { oid => '3051', descr => 'determine if a string is well formed XML', proname => 'xml_is_well_formed', provolatile => 's', prorettype => 'bool', proargtypes => 'text', prosrc => 'xml_is_well_formed' }, |