Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit4b496a3

Browse files
committed
Catch fatal flex errors in the GUC file lexer.
This prevents the postmaster from unexpectedly croaking if postgresql.confcontains something like:include 'invalid_directory_name'Noah Misch. Reviewed by Tom Lane and myself.
1 parent754b814 commit4b496a3

File tree

1 file changed

+53
-12
lines changed

1 file changed

+53
-12
lines changed

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

Lines changed: 53 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,14 @@
2020
#include"utils/guc.h"
2121

2222

23-
/* Avoid exit() on fatal scanner errors (a bit ugly -- see yy_fatal_error) */
23+
/*
24+
* flex emits a yy_fatal_error() function that it calls in response to
25+
* critical errors like malloc failure, file I/O errors, and detection of
26+
* internal inconsistency. That function prints a message and calls exit().
27+
* Mutate it to instead call our handler, which jumps out of the parser.
28+
*/
2429
#undef fprintf
25-
#definefprintf(file, fmt, msg) ereport(ERROR, (errmsg_internal("%s",msg)))
30+
#definefprintf(file, fmt, msg)GUC_flex_fatal(msg)
2631

2732
enum {
2833
GUC_ID =1,
@@ -37,10 +42,13 @@ enum {
3742
};
3843

3944
staticunsignedint ConfigFileLineno;
45+
staticconstchar *GUC_flex_fatal_errmsg;
46+
static sigjmp_buf *GUC_flex_fatal_jmp;
4047

4148
/* flex fails to supply a prototype for yylex, so provide one */
4249
intGUC_yylex(void);
4350

51+
staticintGUC_flex_fatal(constchar *msg);
4452
staticchar *GUC_scanstr(constchar *s);
4553

4654
%}
@@ -436,6 +444,22 @@ ParseConfigFile(const char *config_file, const char *calling_file, bool strict,
436444
return OK;
437445
}
438446

447+
/*
448+
* Flex fatal errors bring us here. Stash the error message and jump back to
449+
* ParseConfigFp(). Assume all msg arguments point to string constants; this
450+
* holds for flex 2.5.31 (earliest we support) and flex 2.5.35 (latest as of
451+
* this writing). Otherwise, we would need to copy the message.
452+
*
453+
* We return "int" since this takes the place of calls to fprintf().
454+
*/
455+
staticint
456+
GUC_flex_fatal(constchar *msg)
457+
{
458+
GUC_flex_fatal_errmsg = msg;
459+
siglongjmp(*GUC_flex_fatal_jmp,1);
460+
return0;/* keep compiler quiet */
461+
}
462+
439463
/*
440464
* Read and parse a single configuration file. This function recurses
441465
* to handle "include" directives.
@@ -464,19 +488,38 @@ ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel,
464488
ConfigVariable **head_p, ConfigVariable **tail_p)
465489
{
466490
boolOK =true;
467-
YY_BUFFER_STATE lex_buffer;
491+
unsignedint save_ConfigFileLineno = ConfigFileLineno;
492+
sigjmp_buf *save_GUC_flex_fatal_jmp = GUC_flex_fatal_jmp;
493+
sigjmp_bufflex_fatal_jmp;
494+
volatile YY_BUFFER_STATE lex_buffer =NULL;
468495
interrorcount;
469496
inttoken;
470497

498+
if (sigsetjmp(flex_fatal_jmp,1) ==0)
499+
GUC_flex_fatal_jmp = &flex_fatal_jmp;
500+
else
501+
{
502+
/*
503+
* Regain control after a fatal, internal flex error. It may have
504+
* corrupted parser state. Consequently, abandon the file, but trust
505+
* that the state remains sane enough for yy_delete_buffer().
506+
*/
507+
elog(elevel,"%s at file\"%s\" line %u",
508+
GUC_flex_fatal_errmsg, config_file, ConfigFileLineno);
509+
510+
OK =false;
511+
goto cleanup;
512+
}
513+
471514
/*
472515
* Parse
473516
*/
474-
lex_buffer =yy_create_buffer(fp, YY_BUF_SIZE);
475-
yy_switch_to_buffer(lex_buffer);
476-
477517
ConfigFileLineno =1;
478518
errorcount =0;
479519

520+
lex_buffer =yy_create_buffer(fp, YY_BUF_SIZE);
521+
yy_switch_to_buffer(lex_buffer);
522+
480523
/* This loop iterates once per logical line */
481524
while ((token =yylex()))
482525
{
@@ -526,14 +569,11 @@ ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel,
526569
* An include_if_exists directive isn't a variable and should be
527570
* processed immediately.
528571
*/
529-
unsignedint save_ConfigFileLineno = ConfigFileLineno;
530-
531572
if (!ParseConfigFile(opt_value, config_file,false,
532573
depth +1, elevel,
533574
head_p, tail_p))
534575
OK =false;
535576
yy_switch_to_buffer(lex_buffer);
536-
ConfigFileLineno = save_ConfigFileLineno;
537577
pfree(opt_name);
538578
pfree(opt_value);
539579
}
@@ -543,14 +583,11 @@ ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel,
543583
* An include directive isn't a variable and should be processed
544584
* immediately.
545585
*/
546-
unsignedint save_ConfigFileLineno = ConfigFileLineno;
547-
548586
if (!ParseConfigFile(opt_value, config_file,true,
549587
depth +1, elevel,
550588
head_p, tail_p))
551589
OK =false;
552590
yy_switch_to_buffer(lex_buffer);
553-
ConfigFileLineno = save_ConfigFileLineno;
554591
pfree(opt_name);
555592
pfree(opt_value);
556593
}
@@ -620,7 +657,11 @@ ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel,
620657
break;
621658
}
622659

660+
cleanup:
623661
yy_delete_buffer(lex_buffer);
662+
/* Each recursion level must save and restore these static variables. */
663+
ConfigFileLineno = save_ConfigFileLineno;
664+
GUC_flex_fatal_jmp = save_GUC_flex_fatal_jmp;
624665
return OK;
625666
}
626667

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp