Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit fc6da31

Browse files
committed
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.
1 parent 0898033 commit fc6da31

File tree

1 file changed

+77
-78
lines changed

1 file changed

+77
-78
lines changed

src/backend/utils/misc/guc-file.l

Lines changed: 77 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*
55
* Copyright (c) 2000-2005, PostgreSQL Global Development Group
66
*
7-
* $PostgreSQL: pgsql/src/backend/utils/misc/guc-file.l,v 1.32 2005/09/21 20:33:34 tgl Exp $
7+
* $PostgreSQL: pgsql/src/backend/utils/misc/guc-file.l,v 1.33 2006/01/01 19:52:40 tgl Exp $
88
*/
99

1010
%{
@@ -126,7 +126,7 @@ void
126126
ProcessConfigFile(GucContext context)
127127
{
128128
int elevel;
129-
int token, parse_state;
129+
int token;
130130
char *opt_name, *opt_value;
131131
struct name_value_pair *item, *head, *tail;
132132
FILE *fp;
@@ -144,109 +144,108 @@ ProcessConfigFile(GucContext context)
144144
else
145145
elevel = ERROR;
146146
147-
fp = AllocateFile(ConfigFileName, "r");
148-
if (!fp)
149-
{
147+
fp = AllocateFile(ConfigFileName, "r");
148+
if (!fp)
149+
{
150150
ereport(elevel,
151151
(errcode_for_file_access(),
152152
errmsg("could not open configuration file \"%s\": %m",
153153
ConfigFileName)));
154154
return;
155-
}
155+
}
156156
157157
/*
158158
* Parse
159159
*/
160160
yyin = fp;
161-
parse_state = 0;
161+
YY_FLUSH_BUFFER; /* in case we abandoned a prior scan */
162162
head = tail = NULL;
163163
opt_name = opt_value = NULL;
164164
ConfigFileLineno = 1;
165165
166-
while ((token = yylex()))
166+
/* This loop iterates once per logical line */
167+
while ((token = yylex()))
167168
{
168-
switch(parse_state)
169-
{
170-
case 0: /* no previous input */
171-
if (token == GUC_EOL) /* empty line */
172-
continue;
173-
if (token != GUC_ID && token != GUC_QUALIFIED_ID)
174-
goto parse_error;
175-
opt_name = pstrdup(yytext);
176-
parse_state = 1;
177-
break;
178-
179-
case 1: /* found name */
180-
/* ignore equals sign */
181-
if (token == GUC_EQUALS)
182-
token = yylex();
183-
184-
if (token != GUC_ID &&
185-
token != GUC_STRING &&
186-
token != GUC_INTEGER &&
187-
token != GUC_REAL &&
188-
token != GUC_UNQUOTED_STRING)
189-
goto parse_error;
190-
if (token == GUC_STRING) /* strip quotes and escapes */
191-
opt_value = GUC_scanstr(yytext);
192-
else
193-
opt_value = pstrdup(yytext);
194-
parse_state = 2;
195-
break;
196-
197-
case 2: /* now we'd like an end of line */
198-
if (token != GUC_EOL)
199-
goto parse_error;
200-
201-
if (strcmp(opt_name, "custom_variable_classes") == 0)
202-
{
203-
/*
204-
* This variable must be processed first as it controls
205-
* the validity of other variables; so apply immediately.
206-
*/
207-
if (!set_config_option(opt_name, opt_value, context,
208-
PGC_S_FILE, false, true))
209-
{
210-
pfree(opt_name);
211-
pfree(opt_value);
212-
FreeFile(fp);
213-
goto cleanup_exit;
214-
}
215-
pfree(opt_name);
216-
pfree(opt_value);
217-
}
218-
else
219-
{
220-
/* append to list */
221-
item = palloc(sizeof *item);
222-
item->name = opt_name;
223-
item->value = opt_value;
224-
item->next = NULL;
225-
if (!head)
226-
head = item;
227-
else
228-
tail->next = item;
229-
tail = item;
230-
}
231-
232-
parse_state = 0;
233-
break;
234-
}
169+
if (token == GUC_EOL) /* empty or comment line */
170+
continue;
171+
172+
/* first token on line is option name */
173+
if (token != GUC_ID && token != GUC_QUALIFIED_ID)
174+
goto parse_error;
175+
opt_name = pstrdup(yytext);
176+
177+
/* next we have an optional equal sign; discard if present */
178+
token = yylex();
179+
if (token == GUC_EQUALS)
180+
token = yylex();
181+
182+
/* now we must have the option value */
183+
if (token != GUC_ID &&
184+
token != GUC_STRING &&
185+
token != GUC_INTEGER &&
186+
token != GUC_REAL &&
187+
token != GUC_UNQUOTED_STRING)
188+
goto parse_error;
189+
if (token == GUC_STRING) /* strip quotes and escapes */
190+
opt_value = GUC_scanstr(yytext);
191+
else
192+
opt_value = pstrdup(yytext);
193+
194+
/* now we'd like an end of line, or possibly EOF */
195+
token = yylex();
196+
if (token != GUC_EOL && token != 0)
197+
goto parse_error;
198+
199+
/* OK, save the option name and value */
200+
if (strcmp(opt_name, "custom_variable_classes") == 0)
201+
{
202+
/*
203+
* This variable must be processed first as it controls
204+
* the validity of other variables; so apply immediately.
205+
*/
206+
if (!set_config_option(opt_name, opt_value, context,
207+
PGC_S_FILE, false, true))
208+
{
209+
pfree(opt_name);
210+
pfree(opt_value);
211+
FreeFile(fp);
212+
goto cleanup_exit;
213+
}
214+
pfree(opt_name);
215+
pfree(opt_value);
216+
}
217+
else
218+
{
219+
/* append to list */
220+
item = palloc(sizeof *item);
221+
item->name = opt_name;
222+
item->value = opt_value;
223+
item->next = NULL;
224+
if (!head)
225+
head = item;
226+
else
227+
tail->next = item;
228+
tail = item;
229+
}
230+
231+
/* break out of loop if read EOF, else loop for next line */
232+
if (token == 0)
233+
break;
235234
}
236235

237236
FreeFile(fp);
238237

239238
/*
240239
* Check if all options are valid
241240
*/
242-
for(item = head; item; item=item->next)
241+
for(item = head; item; item=item->next)
243242
{
244243
if (!set_config_option(item->name, item->value, context,
245244
PGC_S_FILE, false, false))
246245
goto cleanup_exit;
247246
}
248247

249-
/* If we got here all the options parsed okay, so apply them. */
248+
/* If we got here all the options parsed okay, so apply them. */
250249
for(item = head; item; item=item->next)
251250
{
252251
set_config_option(item->name, item->value, context,
@@ -260,7 +259,7 @@ ProcessConfigFile(GucContext context)
260259
parse_error:
261260
FreeFile(fp);
262261
free_name_value_list(head);
263-
if (token == GUC_EOL)
262+
if (token == GUC_EOL || token == 0)
264263
ereport(elevel,
265264
(errcode(ERRCODE_SYNTAX_ERROR),
266265
errmsg("syntax error in file \"%s\" line %u, near end of line",

0 commit comments

Comments
 (0)