pg.ddx.io  pgsql-bugs@postgresql.org mailing list archive  
help / color / mirror / Atom feed
From: Michael Paquier <michael@paquier.xyz>
To: Andrey Rachitskiy <pl0h0yp1@gmail.com>
Cc: ilia.kashintsev@gmail.com
Cc: pgsql-bugs@lists.postgresql.org
Subject: Re: BUG #19612: SEGV in ParseConfigFp() in guc-file.l
Date: Thu, 13 Aug 2026 17:27:42 +0900
Message-ID: <an1__bbJ4MNfy9Lp@paquier.xyz> (raw)
In-Reply-To: <CAB8bMivnXcb7RRd=EKdY_nBOqR=6iJPwZx1oEGz+ayfqzj9HVQ@mail.gmail.com>
References: <19612-24ccb4fc6da7786f@postgresql.org>
	<CAB8bMivnXcb7RRd=EKdY_nBOqR=6iJPwZx1oEGz+ayfqzj9HVQ@mail.gmail.com>

On Tue, Aug 11, 2026 at 11:30:03AM +0500, Andrey Rachitskiy wrote:
> Commit 4b496a3583e already marked the YY_BUFFER_STATE local volatile
> for that longjmp path.  Commit d663f150b5e made the scanner reentrant
> and added a yyscan_t local used in the same cleanup.  That local is
> written after sigsetjmp and read after siglongjmp, but was not
> volatile, so its value is indeterminate after the jump.

Asan failure reproduced, thanks.  Your patch has missed the following
piece with yylex_init():
guc-file.l:387:17: warning: passing 'volatile yyscan_t *' (aka 'void
*volatile *') to parameter of type 'yyscan_t *' (aka 'void **')
discards qualifiers
[-Wincompatible-pointer-types-discards-qualifiers]   387 |         if
(yylex_init(&scanner) != 0)

I am wondering whether we should just use a non-volatile copy of
"scanner", just for the sake of yylex_init().  The attached seems to
work fine here with asan.

Thoughts?
--
Michael
diff --git a/src/backend/utils/misc/guc-file.l b/src/backend/utils/misc/guc-file.l
index 58669a67e050..13cdba6cd7b6 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;	/* 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,9 @@ 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");
+	scanner = scanner_init;
 	yyg = (struct yyguts_t *) scanner;
 
 	lex_buffer = yy_create_buffer(fp, YY_BUF_SIZE, scanner);
@@ -559,8 +561,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;

Attachments:

  [text/plain] asan-guc-file-l.patch (1.4K, ../an1__bbJ4MNfy9Lp@paquier.xyz/2-asan-guc-file-l.patch)
  download | inline diff:
diff --git a/src/backend/utils/misc/guc-file.l b/src/backend/utils/misc/guc-file.l
index 58669a67e050..13cdba6cd7b6 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;	/* 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,9 @@ 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");
+	scanner = scanner_init;
 	yyg = (struct yyguts_t *) scanner;
 
 	lex_buffer = yy_create_buffer(fp, YY_BUF_SIZE, scanner);
@@ -559,8 +561,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;

  [application/pgp-signature] signature.asc (832B, ../an1__bbJ4MNfy9Lp@paquier.xyz/3-signature.asc)
  download

view thread (8+ messages)  latest in thread

Message-ID: <an1__bbJ4MNfy9Lp@paquier.xyz>
Permalink:  ../an1__bbJ4MNfy9Lp@paquier.xyz/
Also on:    postgresql.org/message-id/an1__bbJ4MNfy9Lp@paquier.xyz

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: pgsql-bugs@postgresql.org
  Cc: michael@paquier.xyz, pl0h0yp1@gmail.com, ilia.kashintsev@gmail.com, pgsql-bugs@lists.postgresql.org
  Subject: Re: BUG #19612: SEGV in ParseConfigFp() in guc-file.l
  In-Reply-To: <an1__bbJ4MNfy9Lp@paquier.xyz>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox