From aa0bcbbbbe164671a73c9f0702c0fbcadb4a8da4 Mon Sep 17 00:00:00 2001 From: Michael Paquier Date: Sun, 16 Aug 2026 14:49:16 +0900 Subject: [PATCH v2] Fix ASAN failure after flex errors in GUC file parsing As detected by ASAN, the scanner value used when parsing GUC files can be indeterminate when the flex error handler sigjumps to old cleanup path, before yylex_init() is called. The flex scanner state is now made volatile in ParseConfigFp(), since its value is assigned after sigsetjmp() and cna be accessed after siglongjmp(). yylex_init() cannot use a volatile pointer; a temporary variable is used before assigning the result of yylex_init() to it. Oversight in d663f150b5ed. Reported-by: Ilia Kashintsev Discussion: https://postgr.es/m/19612-24ccb4fc6da7786f@postgresql.org Backpatch-through: 18 --- src/backend/utils/misc/guc-file.l | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/backend/utils/misc/guc-file.l b/src/backend/utils/misc/guc-file.l index 58669a67e050..84c102717eeb 100644 --- a/src/backend/utils/misc/guc-file.l +++ b/src/backend/utils/misc/guc-file.l @@ -354,7 +354,8 @@ ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel, unsigned int save_ConfigFileLineno = ConfigFileLineno; sigjmp_buf *save_GUC_flex_fatal_jmp = GUC_flex_fatal_jmp; sigjmp_buf flex_fatal_jmp; - yyscan_t scanner; + volatile yyscan_t scanner = NULL; + yyscan_t scanner_init = NULL; /* non-volatile for yylex_init() */ struct yyguts_t *yyg; /* needed for yytext macro */ volatile YY_BUFFER_STATE lex_buffer = NULL; int errorcount; @@ -384,8 +385,12 @@ ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel, ConfigFileLineno = 1; errorcount = 0; - if (yylex_init(&scanner) != 0) + if (yylex_init(&scanner_init) != 0) + { elog(elevel, "yylex_init() failed: %m"); + goto cleanup; + } + scanner = scanner_init; yyg = (struct yyguts_t *) scanner; lex_buffer = yy_create_buffer(fp, YY_BUF_SIZE, scanner); @@ -559,8 +564,11 @@ parse_error: } cleanup: - yy_delete_buffer(lex_buffer, scanner); - yylex_destroy(scanner); + if (scanner) + { + yy_delete_buffer(lex_buffer, scanner); + yylex_destroy(scanner); + } /* Each recursion level must save and restore these static variables. */ ConfigFileLineno = save_ConfigFileLineno; GUC_flex_fatal_jmp = save_GUC_flex_fatal_jmp; -- 2.55.0