From 0f319818360cdd26e96198ea7fcaba1b8298f264 Mon Sep 17 00:00:00 2001
From: Erik Wienhold <ewie@ewie.name>
Date: Tue, 14 May 2024 04:14:08 +0200
Subject: [PATCH] Fix parsing of positional parameters with underscores

Underscores were added to numeric literals in faff8f8e47.  That also
introduced a regression whereby positional parameters accepted
underscores as well.  But such parameter numbers were not parsed
correctly by atol which stops at the first non-digit character.  So
parameter $1_2 would be taken as just $1.  Fix that by replacing atol
with pg_strtoint32_safe.  Thereby we also avoid the undefined behavior
of atol on overflows.
---
 src/backend/parser/scan.l                | 5 ++++-
 src/test/regress/expected/numerology.out | 1 +
 src/test/regress/sql/numerology.sql      | 2 ++
 3 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/src/backend/parser/scan.l b/src/backend/parser/scan.l
index 5eaadf53b2..ebb7ace9ca 100644
--- a/src/backend/parser/scan.l
+++ b/src/backend/parser/scan.l
@@ -992,7 +992,10 @@ other			.
 
 {param}			{
 					SET_YYLLOC();
-					yylval->ival = atol(yytext + 1);
+					ErrorSaveContext escontext = {T_ErrorSaveContext};
+					yylval->ival = pg_strtoint32_safe(yytext + 1, (Node *) &escontext);
+					if (escontext.error_occurred)
+						yyerror("parameter too large");
 					return PARAM;
 				}
 {param_junk}	{
diff --git a/src/test/regress/expected/numerology.out b/src/test/regress/expected/numerology.out
index f662a5050a..3c1308e22c 100644
--- a/src/test/regress/expected/numerology.out
+++ b/src/test/regress/expected/numerology.out
@@ -297,6 +297,7 @@ SELECT 1_000.5e0_1;
     10005
 (1 row)
 
+PREPARE p2 AS SELECT $0_1;
 -- error cases
 SELECT _100;
 ERROR:  column "_100" does not exist
diff --git a/src/test/regress/sql/numerology.sql b/src/test/regress/sql/numerology.sql
index 1941c58e68..11af76828d 100644
--- a/src/test/regress/sql/numerology.sql
+++ b/src/test/regress/sql/numerology.sql
@@ -77,6 +77,8 @@ SELECT 1_000.;
 SELECT .000_005;
 SELECT 1_000.5e0_1;
 
+PREPARE p2 AS SELECT $0_1;
+
 -- error cases
 SELECT _100;
 SELECT 100_;
-- 
2.45.0

