*** a/src/backend/utils/misc/guc-file.l --- b/src/backend/utils/misc/guc-file.l *************** *** 20,28 **** #include "utils/guc.h" ! /* Avoid exit() on fatal scanner errors (a bit ugly -- see yy_fatal_error) */ #undef fprintf ! #define fprintf(file, fmt, msg) ereport(ERROR, (errmsg_internal("%s", msg))) enum { GUC_ID = 1, --- 20,41 ---- #include "utils/guc.h" ! /* ! * flex emits a yy_fatal_error() function that it calls in response to ! * critical errors like malloc failure, file I/O errors, and detection of ! * internal inconsistency. That function prints a message and calls exit(). ! * Mutate it to instead stash the message and jump out of the parser; see ! * GUC_safe_yylex() for the other half of the story. Assume all msg arguments ! * point to string constants; this holds for flex 2.5.31 (earliest we support) ! * and flex 2.5.35 (latest as of this writing). ! */ ! static const char *GUC_flex_fatal_errmsg; ! static sigjmp_buf GUC_flex_fatal_jmp; #undef fprintf ! #define fprintf(file, fmt, msg) \ ! 0; /* eat cast to void */ \ ! GUC_flex_fatal_errmsg = msg; \ ! siglongjmp(GUC_flex_fatal_jmp, 1) enum { GUC_ID = 1, *************** *** 32,39 **** enum { GUC_EQUALS = 5, GUC_UNQUOTED_STRING = 6, GUC_QUALIFIED_ID = 7, ! GUC_EOL = 99, ! GUC_ERROR = 100 }; static unsigned int ConfigFileLineno; --- 45,53 ---- GUC_EQUALS = 5, GUC_UNQUOTED_STRING = 6, GUC_QUALIFIED_ID = 7, ! GUC_EOL = 98, ! GUC_ERROR = 99, ! GUC_INTERNAL_ERROR = 100 }; static unsigned int ConfigFileLineno; *************** *** 437,442 **** ParseConfigFile(const char *config_file, const char *calling_file, bool strict, --- 451,469 ---- } /* + * Wrap the generated lexer so we can regain control after a fatal, internal + * flex error. On return of GUC_INTERNAL_ERROR, GUC_flex_fatal_errmsg will + * contain a pointer into static storage containing the error message. + */ + static int + GUC_safe_yylex(void) + { + if (sigsetjmp(GUC_flex_fatal_jmp, 1) != 0) + return GUC_INTERNAL_ERROR; + return GUC_yylex(); + } + + /* * Read and parse a single configuration file. This function recurses * to handle "include" directives. * *************** *** 478,484 **** ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel, errorcount = 0; /* This loop iterates once per logical line */ ! while ((token = yylex())) { char *opt_name = NULL; char *opt_value = NULL; --- 505,511 ---- errorcount = 0; /* This loop iterates once per logical line */ ! while ((token = GUC_safe_yylex())) { char *opt_name = NULL; char *opt_value = NULL; *************** *** 493,501 **** ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel, opt_name = pstrdup(yytext); /* next we have an optional equal sign; discard if present */ ! token = yylex(); if (token == GUC_EQUALS) ! token = yylex(); /* now we must have the option value */ if (token != GUC_ID && --- 520,528 ---- opt_name = pstrdup(yytext); /* next we have an optional equal sign; discard if present */ ! token = GUC_safe_yylex(); if (token == GUC_EQUALS) ! token = GUC_safe_yylex(); /* now we must have the option value */ if (token != GUC_ID && *************** *** 510,516 **** ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel, opt_value = pstrdup(yytext); /* now we'd like an end of line, or possibly EOF */ ! token = yylex(); if (token != GUC_EOL) { if (token != 0) --- 537,543 ---- opt_value = pstrdup(yytext); /* now we'd like an end of line, or possibly EOF */ ! token = GUC_safe_yylex(); if (token != GUC_EOL) { if (token != 0) *************** *** 583,589 **** ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel, pfree(opt_value); /* report the error */ ! if (token == GUC_EOL || token == 0) ereport(elevel, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("syntax error in file \"%s\" line %u, near end of line", --- 610,619 ---- pfree(opt_value); /* report the error */ ! if (token == GUC_INTERNAL_ERROR) ! elog(elevel, "%s at file \"%s\" line %u", ! GUC_flex_fatal_errmsg, config_file, ConfigFileLineno); ! else if (token == GUC_EOL || token == 0) ereport(elevel, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("syntax error in file \"%s\" line %u, near end of line", *************** *** 612,622 **** ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel, break; } ! /* resync to next end-of-line or EOF */ ! while (token != GUC_EOL && token != 0) ! token = yylex(); ! /* break out of loop on EOF */ ! if (token == 0) break; } --- 642,655 ---- break; } ! /* ! * Resync to next end-of-line or EOF. Abandon the file after a ! * flex-internal error, which may corrupt parser state. Hopefully, ! * it's not so corrupt that yy_delete_buffer() will explode... ! */ ! while (token != GUC_EOL && token != 0 && token != GUC_INTERNAL_ERROR) ! token = GUC_safe_yylex(); ! if (token != GUC_EOL) break; }