From c7181a32c57d97b7a899776dabae6892e2b98b93 Mon Sep 17 00:00:00 2001 From: John Naylor Date: Fri, 30 Jul 2021 13:50:23 -0400 Subject: [PATCH] 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 --- doc/src/sgml/ecpg.sgml | 2 +- src/interfaces/ecpg/pgtypeslib/numeric.c | 7 ++++++- .../ecpg/test/expected/pgtypeslib-num_test.c | 21 ++++++++++++++----- .../test/expected/pgtypeslib-num_test.stderr | 2 +- .../test/expected/pgtypeslib-num_test.stdout | 2 ++ .../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 b4e6966405..e94073f461 100644 --- a/doc/src/sgml/ecpg.sgml +++ b/doc/src/sgml/ecpg.sgml @@ -8618,7 +8618,7 @@ int dectoint(decimal *np, int *ip); Note that the ECPG implementation differs from the Informix implementation. Informix limits an integer to the range from -32767 to 32767, while the limits in the ECPG implementation depend on the - architecture (-INT_MAX .. INT_MAX). + architecture (INT_MIN .. INT_MAX). diff --git a/src/interfaces/ecpg/pgtypeslib/numeric.c b/src/interfaces/ecpg/pgtypeslib/numeric.c index 6643242ab1..88a4302faa 100644 --- a/src/interfaces/ecpg/pgtypeslib/numeric.c +++ b/src/interfaces/ecpg/pgtypeslib/numeric.c @@ -1586,12 +1586,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 1b1239eaca..43d1e15c17 100644 --- a/src/interfaces/ecpg/test/expected/pgtypeslib-num_test.c +++ b/src/interfaces/ecpg/test/expected/pgtypeslib-num_test.c @@ -47,7 +47,7 @@ main(void) double d; long l1, l2; - int i; + int i, min, max; ECPGdebug(1, stderr); /* exec sql whenever sqlerror do sqlprint ( ) ; */ @@ -144,17 +144,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 93 "num_test.pgc" +#line 104 "num_test.pgc" if (sqlca.sqlcode < 0) sqlprint ( );} -#line 93 "num_test.pgc" +#line 104 "num_test.pgc" { ECPGdisconnect(__LINE__, "CURRENT"); -#line 94 "num_test.pgc" +#line 105 "num_test.pgc" if (sqlca.sqlcode < 0) sqlprint ( );} -#line 94 "num_test.pgc" +#line 105 "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 d834c22aab..c57fe8b7a9 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 66: RESULT: 2369.7000000 offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ECPGtrans on line 93: action "rollback"; connection "ecpg1_regression" +[NO_PID]: ECPGtrans on line 104: 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 52515ebde2..459d4bffd8 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.330700e+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 9891270494..7bdd375df1 100644 --- a/src/interfaces/ecpg/test/pgtypeslib/num_test.pgc +++ b/src/interfaces/ecpg/test/pgtypeslib/num_test.pgc @@ -24,7 +24,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(); @@ -90,6 +90,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;