Commit fc6da31a authored by Tom Lane's avatar Tom Lane

Rewrite ProcessConfigFile() to avoid misbehavior at EOF, as per report

from Andrus Moor.  The former state-machine-style coding wasn't actually
doing much except obscuring the control flow, and it didn't extend
readily to fix this case, so I just took it out.  Also, add a
YY_FLUSH_BUFFER call to ensure the lexer is reset correctly if the
previous scan failed partway through the file.
parent 0898033b
...@@ -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.32 2005/09/21 20:33:34 tgl Exp $ * $PostgreSQL: pgsql/src/backend/utils/misc/guc-file.l,v 1.33 2006/01/01 19:52:40 tgl Exp $
*/ */
%{ %{
...@@ -126,7 +126,7 @@ void ...@@ -126,7 +126,7 @@ void
ProcessConfigFile(GucContext context) ProcessConfigFile(GucContext context)
{ {
int elevel; int elevel;
int token, parse_state; int token;
char *opt_name, *opt_value; char *opt_name, *opt_value;
struct name_value_pair *item, *head, *tail; struct name_value_pair *item, *head, *tail;
FILE *fp; FILE *fp;
...@@ -144,94 +144,93 @@ ProcessConfigFile(GucContext context) ...@@ -144,94 +144,93 @@ ProcessConfigFile(GucContext context)
else else
elevel = ERROR; elevel = ERROR;
fp = AllocateFile(ConfigFileName, "r"); fp = AllocateFile(ConfigFileName, "r");
if (!fp) if (!fp)
{ {
ereport(elevel, ereport(elevel,
(errcode_for_file_access(), (errcode_for_file_access(),
errmsg("could not open configuration file \"%s\": %m", errmsg("could not open configuration file \"%s\": %m",
ConfigFileName))); ConfigFileName)));
return; return;
} }
/* /*
* Parse * Parse
*/ */
yyin = fp; yyin = fp;
parse_state = 0; YY_FLUSH_BUFFER; /* in case we abandoned a prior scan */
head = tail = NULL; head = tail = NULL;
opt_name = opt_value = NULL; opt_name = opt_value = NULL;
ConfigFileLineno = 1; ConfigFileLineno = 1;
while ((token = yylex())) /* This loop iterates once per logical line */
while ((token = yylex()))
{ {
switch(parse_state) if (token == GUC_EOL) /* empty or comment line */
{ continue;
case 0: /* no previous input */
if (token == GUC_EOL) /* empty line */ /* first token on line is option name */
continue; if (token != GUC_ID && token != GUC_QUALIFIED_ID)
if (token != GUC_ID && token != GUC_QUALIFIED_ID) goto parse_error;
goto parse_error; opt_name = pstrdup(yytext);
opt_name = pstrdup(yytext);
parse_state = 1; /* next we have an optional equal sign; discard if present */
break; token = yylex();
if (token == GUC_EQUALS)
case 1: /* found name */ token = yylex();
/* ignore equals sign */
if (token == GUC_EQUALS) /* now we must have the option value */
token = yylex(); if (token != GUC_ID &&
token != GUC_STRING &&
if (token != GUC_ID && token != GUC_INTEGER &&
token != GUC_STRING && token != GUC_REAL &&
token != GUC_INTEGER && token != GUC_UNQUOTED_STRING)
token != GUC_REAL && goto parse_error;
token != GUC_UNQUOTED_STRING) if (token == GUC_STRING) /* strip quotes and escapes */
goto parse_error; opt_value = GUC_scanstr(yytext);
if (token == GUC_STRING) /* strip quotes and escapes */ else
opt_value = GUC_scanstr(yytext); opt_value = pstrdup(yytext);
else
opt_value = pstrdup(yytext); /* now we'd like an end of line, or possibly EOF */
parse_state = 2; token = yylex();
break; if (token != GUC_EOL && token != 0)
goto parse_error;
case 2: /* now we'd like an end of line */
if (token != GUC_EOL) /* OK, save the option name and value */
goto parse_error; if (strcmp(opt_name, "custom_variable_classes") == 0)
{
if (strcmp(opt_name, "custom_variable_classes") == 0) /*
{ * This variable must be processed first as it controls
/* * the validity of other variables; so apply immediately.
* This variable must be processed first as it controls */
* the validity of other variables; so apply immediately. if (!set_config_option(opt_name, opt_value, context,
*/ PGC_S_FILE, false, true))
if (!set_config_option(opt_name, opt_value, context, {
PGC_S_FILE, false, true)) pfree(opt_name);
{ pfree(opt_value);
pfree(opt_name); FreeFile(fp);
pfree(opt_value); goto cleanup_exit;
FreeFile(fp); }
goto cleanup_exit; pfree(opt_name);
} pfree(opt_value);
pfree(opt_name); }
pfree(opt_value); else
} {
else /* append to list */
{ item = palloc(sizeof *item);
/* append to list */ item->name = opt_name;
item = palloc(sizeof *item); item->value = opt_value;
item->name = opt_name; item->next = NULL;
item->value = opt_value; if (!head)
item->next = NULL; head = item;
if (!head) else
head = item; tail->next = item;
else tail = item;
tail->next = item; }
tail = item;
} /* break out of loop if read EOF, else loop for next line */
if (token == 0)
parse_state = 0; break;
break;
}
} }
FreeFile(fp); FreeFile(fp);
...@@ -239,14 +238,14 @@ ProcessConfigFile(GucContext context) ...@@ -239,14 +238,14 @@ ProcessConfigFile(GucContext context)
/* /*
* Check if all options are valid * Check if all options are valid
*/ */
for(item = head; item; item=item->next) for(item = head; item; item=item->next)
{ {
if (!set_config_option(item->name, item->value, context, if (!set_config_option(item->name, item->value, context,
PGC_S_FILE, false, false)) PGC_S_FILE, false, false))
goto cleanup_exit; goto cleanup_exit;
} }
/* If we got here all the options parsed okay, so apply them. */ /* If we got here all the options parsed okay, so apply them. */
for(item = head; item; item=item->next) for(item = head; item; item=item->next)
{ {
set_config_option(item->name, item->value, context, set_config_option(item->name, item->value, context,
...@@ -260,7 +259,7 @@ ProcessConfigFile(GucContext context) ...@@ -260,7 +259,7 @@ ProcessConfigFile(GucContext context)
parse_error: parse_error:
FreeFile(fp); FreeFile(fp);
free_name_value_list(head); free_name_value_list(head);
if (token == GUC_EOL) if (token == GUC_EOL || token == 0)
ereport(elevel, ereport(elevel,
(errcode(ERRCODE_SYNTAX_ERROR), (errcode(ERRCODE_SYNTAX_ERROR),
errmsg("syntax error in file \"%s\" line %u, near end of line", errmsg("syntax error in file \"%s\" line %u, near end of line",
......
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