From debc576256d53a2c4ca46c3ca117500f16998f7b Mon Sep 17 00:00:00 2001 From: Erik Wienhold Date: Tue, 14 May 2024 14:12:11 +0200 Subject: [PATCH v2 2/2] Fix overflow in parsing of positional parameter Replace atol with pg_strtoint32_safe in the backend parser and with strtoint in ECPG to reject overflows when parsing the number of a positional parameter. With atol from glibc, parameters $2147483648 and $4294967297 turn into $-2147483648 and $1, respectively. --- src/backend/parser/scan.l | 5 ++++- src/interfaces/ecpg/preproc/pgc.l | 5 ++++- src/test/regress/expected/numerology.out | 4 ++++ src/test/regress/sql/numerology.sql | 1 + 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/backend/parser/scan.l b/src/backend/parser/scan.l index b499975e9c..a4f6973950 100644 --- a/src/backend/parser/scan.l +++ b/src/backend/parser/scan.l @@ -993,7 +993,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/interfaces/ecpg/preproc/pgc.l b/src/interfaces/ecpg/preproc/pgc.l index d117cafce6..178686e413 100644 --- a/src/interfaces/ecpg/preproc/pgc.l +++ b/src/interfaces/ecpg/preproc/pgc.l @@ -938,7 +938,10 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ } {param} { - base_yylval.ival = atol(yytext+1); + errno = 0; + base_yylval.ival = strtoint(yytext+1, NULL, 10); + if (errno == ERANGE) + mmfatal(PARSE_ERROR, "parameter too large"); return PARAM; } {param_junk} { diff --git a/src/test/regress/expected/numerology.out b/src/test/regress/expected/numerology.out index c8196d2c85..f9b7eb2764 100644 --- a/src/test/regress/expected/numerology.out +++ b/src/test/regress/expected/numerology.out @@ -206,6 +206,10 @@ PREPARE p1 AS SELECT $1a; ERROR: trailing junk after parameter at or near "$1a" LINE 1: PREPARE p1 AS SELECT $1a; ^ +PREPARE p1 AS SELECT $2147483648; +ERROR: parameter too large at or near "$2147483648" +LINE 1: PREPARE p1 AS SELECT $2147483648; + ^ SELECT 0b; ERROR: invalid binary integer at or near "0b" LINE 1: SELECT 0b; diff --git a/src/test/regress/sql/numerology.sql b/src/test/regress/sql/numerology.sql index 3f0ec34ecf..6722a09c5f 100644 --- a/src/test/regress/sql/numerology.sql +++ b/src/test/regress/sql/numerology.sql @@ -52,6 +52,7 @@ SELECT 0.0e1a; SELECT 0.0e; SELECT 0.0e+a; PREPARE p1 AS SELECT $1a; +PREPARE p1 AS SELECT $2147483648; SELECT 0b; SELECT 1b; -- 2.45.0