diff options
author | John Naylor <john.naylor@postgresql.org> | 2021-07-30 13:50:23 -0400 |
---|---|---|
committer | John Naylor <john.naylor@postgresql.org> | 2021-07-30 15:39:22 -0400 |
commit | 5fcf3945bd90bb0170938ad780159779367dc8ac (patch) | |
tree | f80fe11c3a557d6479fd2930ba3cb008dc4d0c36 | |
parent | 3dddb2a8219d3cfd163a83561d4b4613cd2ea376 (diff) | |
download | postgresql-5fcf3945bd90bb0170938ad780159779367dc8ac.tar.gz postgresql-5fcf3945bd90bb0170938ad780159779367dc8ac.zip |
Fix range check in ECPG numeric to int conversion
The previous coding guarded against -INT_MAX instead of INT_MIN,
leading to -2147483648 being rejected as out of range.
Per bug #17128 from Kevin Sweet
Discussion: https://www.postgresql.org/message-id/flat/17128-55a8a879727a3e3a%40postgresql.org
Reviewed-by: Tom Lane
Backpatch to all supported branches
-rw-r--r-- | doc/src/sgml/ecpg.sgml | 2 | ||||
-rw-r--r-- | src/interfaces/ecpg/pgtypeslib/numeric.c | 7 | ||||
-rw-r--r-- | src/interfaces/ecpg/test/expected/pgtypeslib-num_test.c | 21 | ||||
-rw-r--r-- | src/interfaces/ecpg/test/expected/pgtypeslib-num_test.stderr | 2 | ||||
-rw-r--r-- | src/interfaces/ecpg/test/expected/pgtypeslib-num_test.stdout | 2 | ||||
-rw-r--r-- | src/interfaces/ecpg/test/pgtypeslib/num_test.pgc | 13 |
6 files changed, 38 insertions, 9 deletions
diff --git a/doc/src/sgml/ecpg.sgml b/doc/src/sgml/ecpg.sgml index 9d5505cb849..04d4a6bdb2b 100644 --- a/doc/src/sgml/ecpg.sgml +++ b/doc/src/sgml/ecpg.sgml @@ -8881,7 +8881,7 @@ int dectoint(decimal *np, int *ip); Note that the ECPG implementation differs from the <productname>Informix</productname> implementation. <productname>Informix</productname> limits an integer to the range from -32767 to 32767, while the limits in the ECPG implementation depend on the - architecture (<literal>-INT_MAX .. INT_MAX</literal>). + architecture (<literal>INT_MIN .. INT_MAX</literal>). </para> </listitem> </varlistentry> diff --git a/src/interfaces/ecpg/pgtypeslib/numeric.c b/src/interfaces/ecpg/pgtypeslib/numeric.c index 060fad7867d..dbe4eb21e27 100644 --- a/src/interfaces/ecpg/pgtypeslib/numeric.c +++ b/src/interfaces/ecpg/pgtypeslib/numeric.c @@ -1505,12 +1505,17 @@ PGTYPESnumeric_to_int(numeric *nv, int *ip) if ((i = PGTYPESnumeric_to_long(nv, &l)) != 0) return i; - if (l < -INT_MAX || l > INT_MAX) +/* silence compilers that might complain about useless tests */ +#if SIZEOF_LONG > SIZEOF_INT + + if (l < INT_MIN || l > INT_MAX) { errno = PGTYPES_NUM_OVERFLOW; return -1; } +#endif + *ip = (int) l; return 0; } diff --git a/src/interfaces/ecpg/test/expected/pgtypeslib-num_test.c b/src/interfaces/ecpg/test/expected/pgtypeslib-num_test.c index bf312549b4f..ddb78600e39 100644 --- a/src/interfaces/ecpg/test/expected/pgtypeslib-num_test.c +++ b/src/interfaces/ecpg/test/expected/pgtypeslib-num_test.c @@ -75,7 +75,7 @@ main(void) double d; long l1, l2; - int i; + int i, min, max; ECPGdebug(1, stderr); /* exec sql whenever sqlerror do sqlprint ( ) ; */ @@ -174,17 +174,28 @@ if (sqlca.sqlcode < 0) sqlprint ( );} PGTYPESnumeric_free(value2); PGTYPESnumeric_free(res); + /* check conversion of numeric to int */ + value1 = PGTYPESnumeric_from_asc("-2147483648", NULL); + PGTYPESnumeric_to_int(value1, &min); + printf("min int = %d\n", min); + PGTYPESnumeric_free(value1); + + value2 = PGTYPESnumeric_from_asc("2147483647", NULL); + PGTYPESnumeric_to_int(value2, &max); + printf("max int = %d\n", max); + PGTYPESnumeric_free(value2); + { ECPGtrans(__LINE__, NULL, "rollback"); -#line 90 "num_test.pgc" +#line 101 "num_test.pgc" if (sqlca.sqlcode < 0) sqlprint ( );} -#line 90 "num_test.pgc" +#line 101 "num_test.pgc" { ECPGdisconnect(__LINE__, "CURRENT"); -#line 91 "num_test.pgc" +#line 102 "num_test.pgc" if (sqlca.sqlcode < 0) sqlprint ( );} -#line 91 "num_test.pgc" +#line 102 "num_test.pgc" return 0; diff --git a/src/interfaces/ecpg/test/expected/pgtypeslib-num_test.stderr b/src/interfaces/ecpg/test/expected/pgtypeslib-num_test.stderr index a7d125402af..10cfd91cec7 100644 --- a/src/interfaces/ecpg/test/expected/pgtypeslib-num_test.stderr +++ b/src/interfaces/ecpg/test/expected/pgtypeslib-num_test.stderr @@ -26,7 +26,7 @@ [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ecpg_get_data on line 61: RESULT: 2369.7000000 offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ECPGtrans on line 90: action "rollback"; connection "ecpg1_regression" +[NO_PID]: ECPGtrans on line 101: action "rollback"; connection "ecpg1_regression" [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ecpg_finish: connection ecpg1_regression closed [NO_PID]: sqlca: code: 0, state: 00000 diff --git a/src/interfaces/ecpg/test/expected/pgtypeslib-num_test.stdout b/src/interfaces/ecpg/test/expected/pgtypeslib-num_test.stdout index 204c3cf6c07..a47a044c3a4 100644 --- a/src/interfaces/ecpg/test/expected/pgtypeslib-num_test.stdout +++ b/src/interfaces/ecpg/test/expected/pgtypeslib-num_test.stdout @@ -4,3 +4,5 @@ sub = 2369.7 mul = 13306998429.873000000 div = 1330699.84298730000 1.3307e+06 to long(0) = 20000000 14 +min int = -2147483648 +max int = 2147483647 diff --git a/src/interfaces/ecpg/test/pgtypeslib/num_test.pgc b/src/interfaces/ecpg/test/pgtypeslib/num_test.pgc index 254aeb4129b..c6c2858b818 100644 --- a/src/interfaces/ecpg/test/pgtypeslib/num_test.pgc +++ b/src/interfaces/ecpg/test/pgtypeslib/num_test.pgc @@ -19,7 +19,7 @@ main(void) exec sql end declare section; double d; long l1, l2; - int i; + int i, min, max; ECPGdebug(1, stderr); exec sql whenever sqlerror do sqlprint(); @@ -87,6 +87,17 @@ main(void) PGTYPESnumeric_free(value2); PGTYPESnumeric_free(res); + /* check conversion of numeric to int */ + value1 = PGTYPESnumeric_from_asc("-2147483648", NULL); + PGTYPESnumeric_to_int(value1, &min); + printf("min int = %d\n", min); + PGTYPESnumeric_free(value1); + + value2 = PGTYPESnumeric_from_asc("2147483647", NULL); + PGTYPESnumeric_to_int(value2, &max); + printf("max int = %d\n", max); + PGTYPESnumeric_free(value2); + exec sql rollback; exec sql disconnect; |