diff options
author | Peter Eisentraut | 2024-07-02 07:16:36 +0000 |
---|---|---|
committer | Peter Eisentraut | 2024-07-02 07:29:26 +0000 |
commit | d35cd061998434747c0d1c0f6f2aa1f736f0edb4 (patch) | |
tree | 36ed3648c04c61639f7ee19a00a6698042093c13 | |
parent | 4867f8a555cea1bc6de1726b0030896aa4cd3c70 (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.l | 8 | ||||
-rw-r--r-- | src/interfaces/ecpg/preproc/pgc.l | 8 | ||||
-rw-r--r-- | src/test/regress/expected/numerology.out | 4 | ||||
-rw-r--r-- | src/test/regress/sql/numerology.sql | 1 |
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; |