From 5fcf3945bd90bb0170938ad780159779367dc8ac 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 9d5505cb84..04d4a6bdb2 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 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 060fad7867..dbe4eb21e2 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 bf312549b4..ddb78600e3 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 a7d125402a..10cfd91cec 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 204c3cf6c0..a47a044c3a 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 254aeb4129..c6c2858b81 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;