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
This commit is contained in:
John Naylor 2021-07-30 13:50:23 -04:00
parent 3dddb2a821
commit 5fcf3945bd
6 changed files with 38 additions and 9 deletions

View File

@ -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>

View File

@ -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;
}

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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;