summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Eisentraut2024-07-02 07:16:36 +0000
committerPeter Eisentraut2024-07-02 07:29:26 +0000
commitd35cd061998434747c0d1c0f6f2aa1f736f0edb4 (patch)
tree36ed3648c04c61639f7ee19a00a6698042093c13
parent4867f8a555cea1bc6de1726b0030896aa4cd3c70 (diff)
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. Author: Erik Wienhold <[email protected]> Reviewed-by: Michael Paquier <[email protected]> Reviewed-by: Peter Eisentraut <[email protected]> Reviewed-by: Alexander Lakhin <[email protected]> Discussion: https://www.postgresql.org/message-id/flat/[email protected]
-rw-r--r--src/backend/parser/scan.l8
-rw-r--r--src/interfaces/ecpg/preproc/pgc.l8
-rw-r--r--src/test/regress/expected/numerology.out4
-rw-r--r--src/test/regress/sql/numerology.sql1
4 files changed, 19 insertions, 2 deletions
diff --git a/src/backend/parser/scan.l b/src/backend/parser/scan.l
index 3248fb51080..f74059e7b0b 100644
--- a/src/backend/parser/scan.l
+++ b/src/backend/parser/scan.l
@@ -992,8 +992,14 @@ other .
}
{param} {
+ ErrorSaveContext escontext = {T_ErrorSaveContext};
+ int32 val;
+
SET_YYLLOC();
- yylval->ival = atol(yytext + 1);
+ val = pg_strtoint32_safe(yytext + 1, (Node *) &escontext);
+ if (escontext.error_occurred)
+ yyerror("parameter number too large");
+ yylval->ival = val;
return PARAM;
}
{param_junk} {
diff --git a/src/interfaces/ecpg/preproc/pgc.l b/src/interfaces/ecpg/preproc/pgc.l
index f9d68a96e79..27261f42d8d 100644
--- a/src/interfaces/ecpg/preproc/pgc.l
+++ b/src/interfaces/ecpg/preproc/pgc.l
@@ -938,7 +938,13 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
}
{param} {
- base_yylval.ival = atol(yytext+1);
+ int val;
+
+ errno = 0;
+ val = strtoint(yytext + 1, NULL, 10);
+ if (errno == ERANGE)
+ mmfatal(PARSE_ERROR, "parameter number too large");
+ base_yylval.ival = val;
return PARAM;
}
{param_junk} {
diff --git a/src/test/regress/expected/numerology.out b/src/test/regress/expected/numerology.out
index 8d4a3ba228a..717a237df98 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 number 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 372e7bf9bc8..3ae491cc980 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;