Commit 1128f556 authored by Tom Lane's avatar Tom Lane

Fix postgresql.conf lexer to accept doubled single quotes in literal

strings.  This is consistent with SQL conventions, and since Bruce
already changed initdb in a way that assumed it worked like this, seems
we'd better make it work like this.
parent dbf95286
<!-- <!--
$PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.18 2005/09/19 17:21:46 momjian Exp $ $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.19 2005/09/21 20:33:33 tgl Exp $
--> -->
<chapter Id="runtime-config"> <chapter Id="runtime-config">
<title>Run-time Configuration</title> <title>Run-time Configuration</title>
...@@ -45,7 +45,8 @@ search_path = '$user, public' ...@@ -45,7 +45,8 @@ search_path = '$user, public'
value is optional. Whitespace is insignificant and blank lines are value is optional. Whitespace is insignificant and blank lines are
ignored. Hash marks (<literal>#</literal>) introduce comments ignored. Hash marks (<literal>#</literal>) introduce comments
anywhere. Parameter values that are not simple identifiers or anywhere. Parameter values that are not simple identifiers or
numbers must be single-quoted. numbers must be single-quoted. To embed a single quote in a parameter
value, write either two quotes (preferred) or backslash-quote.
</para> </para>
<para> <para>
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* *
* Copyright (c) 2000-2005, PostgreSQL Global Development Group * Copyright (c) 2000-2005, PostgreSQL Global Development Group
* *
* $PostgreSQL: pgsql/src/backend/utils/misc/guc-file.l,v 1.31 2005/07/08 18:41:40 tgl Exp $ * $PostgreSQL: pgsql/src/backend/utils/misc/guc-file.l,v 1.32 2005/09/21 20:33:34 tgl Exp $
*/ */
%{ %{
...@@ -38,7 +38,7 @@ enum { ...@@ -38,7 +38,7 @@ enum {
/* prototype, so compiler is happy with our high warnings setting */ /* prototype, so compiler is happy with our high warnings setting */
int GUC_yylex(void); int GUC_yylex(void);
static char *GUC_scanstr(char *); static char *GUC_scanstr(const char *s);
%} %}
%option 8bit %option 8bit
...@@ -64,7 +64,7 @@ ID {LETTER}{LETTER_OR_DIGIT}* ...@@ -64,7 +64,7 @@ ID {LETTER}{LETTER_OR_DIGIT}*
QUALIFIED_ID {ID}"."{ID} QUALIFIED_ID {ID}"."{ID}
UNQUOTED_STRING {LETTER}({LETTER_OR_DIGIT}|[-._:/])* UNQUOTED_STRING {LETTER}({LETTER_OR_DIGIT}|[-._:/])*
STRING \'([^'\n]|\\.)*\' STRING \'([^'\\\n]|\\.|\'\')*\'
%% %%
...@@ -181,22 +181,16 @@ ProcessConfigFile(GucContext context) ...@@ -181,22 +181,16 @@ ProcessConfigFile(GucContext context)
if (token == GUC_EQUALS) if (token == GUC_EQUALS)
token = yylex(); token = yylex();
if (token != GUC_ID && token != GUC_STRING && if (token != GUC_ID &&
token != GUC_STRING &&
token != GUC_INTEGER && token != GUC_INTEGER &&
token != GUC_REAL && token != GUC_REAL &&
token != GUC_UNQUOTED_STRING) token != GUC_UNQUOTED_STRING)
goto parse_error; goto parse_error;
opt_value = pstrdup(yytext); if (token == GUC_STRING) /* strip quotes and escapes */
if (token == GUC_STRING) opt_value = GUC_scanstr(yytext);
{ else
/* remove the beginning and ending quote/apostrophe */ opt_value = pstrdup(yytext);
/* first: shift the whole thing down one character */
memmove(opt_value, opt_value+1, strlen(opt_value)-1);
/* second: null out the 2 characters we shifted */
opt_value[strlen(opt_value)-2] = '\0';
/* do the escape thing. pfree()'s the pstrdup above */
opt_value = GUC_scanstr(opt_value);
}
parse_state = 2; parse_state = 2;
break; break;
...@@ -280,34 +274,33 @@ ProcessConfigFile(GucContext context) ...@@ -280,34 +274,33 @@ ProcessConfigFile(GucContext context)
/* ---------------- /*
* scanstr * scanstr
* *
* if the string passed in has escaped codes, map the escape codes to actual * Strip the quotes surrounding the given string, and collapse any embedded
* chars * '' sequences and backslash escapes.
* *
* the string returned is palloc'd and should eventually be pfree'd by the * the string returned is palloc'd and should eventually be pfree'd by the
* caller; also we assume we should pfree the input string. * caller.
* ----------------
*/ */
static char * static char *
GUC_scanstr(char *s) GUC_scanstr(const char *s)
{ {
char *newStr; char *newStr;
int len, int len,
i, i,
j; j;
if (s == NULL || s[0] == '\0') Assert(s != NULL && s[0] == '\'');
{
if (s != NULL)
pfree(s);
return pstrdup("");
}
len = strlen(s); len = strlen(s);
Assert(len >= 2);
Assert(s[len-1] == '\'');
/* Skip the leading quote; we'll handle the trailing quote below */
s++, len--;
newStr = palloc(len + 1); /* string cannot get longer */ /* Since len still includes trailing quote, this is enough space */
newStr = palloc(len);
for (i = 0, j = 0; i < len; i++) for (i = 0, j = 0; i < len; i++)
{ {
...@@ -354,13 +347,21 @@ GUC_scanstr(char *s) ...@@ -354,13 +347,21 @@ GUC_scanstr(char *s)
default: default:
newStr[j] = s[i]; newStr[j] = s[i];
break; break;
}
} /* switch */ } /* switch */
}
else if (s[i] == '\'' && s[i+1] == '\'')
{
/* doubled quote becomes just one quote */
newStr[j] = s[++i];
}
else else
newStr[j] = s[i]; newStr[j] = s[i];
j++; j++;
} }
newStr[j] = '\0';
pfree(s); /* We copied the ending quote to newStr, so replace with \0 */
Assert(j > 0 && j <= len);
newStr[--j] = '\0';
return newStr; return newStr;
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment