Skip to content

Commit 5fcf394

Browse files
committed
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
1 parent 3dddb2a commit 5fcf394

File tree

6 files changed

+38
-9
lines changed

6 files changed

+38
-9
lines changed

doc/src/sgml/ecpg.sgml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8881,7 +8881,7 @@ int dectoint(decimal *np, int *ip);
88818881
Note that the ECPG implementation differs from the <productname>Informix</productname>
88828882
implementation. <productname>Informix</productname> limits an integer to the range from -32767 to
88838883
32767, while the limits in the ECPG implementation depend on the
8884-
architecture (<literal>-INT_MAX .. INT_MAX</literal>).
8884+
architecture (<literal>INT_MIN .. INT_MAX</literal>).
88858885
</para>
88868886
</listitem>
88878887
</varlistentry>

src/interfaces/ecpg/pgtypeslib/numeric.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1505,12 +1505,17 @@ PGTYPESnumeric_to_int(numeric *nv, int *ip)
15051505
if ((i = PGTYPESnumeric_to_long(nv, &l)) != 0)
15061506
return i;
15071507

1508-
if (l < -INT_MAX || l > INT_MAX)
1508+
/* silence compilers that might complain about useless tests */
1509+
#if SIZEOF_LONG > SIZEOF_INT
1510+
1511+
if (l < INT_MIN || l > INT_MAX)
15091512
{
15101513
errno = PGTYPES_NUM_OVERFLOW;
15111514
return -1;
15121515
}
15131516

1517+
#endif
1518+
15141519
*ip = (int) l;
15151520
return 0;
15161521
}

src/interfaces/ecpg/test/expected/pgtypeslib-num_test.c

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ main(void)
7575

7676
double d;
7777
long l1, l2;
78-
int i;
78+
int i, min, max;
7979

8080
ECPGdebug(1, stderr);
8181
/* exec sql whenever sqlerror do sqlprint ( ) ; */
@@ -174,17 +174,28 @@ if (sqlca.sqlcode < 0) sqlprint ( );}
174174
PGTYPESnumeric_free(value2);
175175
PGTYPESnumeric_free(res);
176176

177+
/* check conversion of numeric to int */
178+
value1 = PGTYPESnumeric_from_asc("-2147483648", NULL);
179+
PGTYPESnumeric_to_int(value1, &min);
180+
printf("min int = %d\n", min);
181+
PGTYPESnumeric_free(value1);
182+
183+
value2 = PGTYPESnumeric_from_asc("2147483647", NULL);
184+
PGTYPESnumeric_to_int(value2, &max);
185+
printf("max int = %d\n", max);
186+
PGTYPESnumeric_free(value2);
187+
177188
{ ECPGtrans(__LINE__, NULL, "rollback");
178-
#line 90 "num_test.pgc"
189+
#line 101 "num_test.pgc"
179190

180191
if (sqlca.sqlcode < 0) sqlprint ( );}
181-
#line 90 "num_test.pgc"
192+
#line 101 "num_test.pgc"
182193

183194
{ ECPGdisconnect(__LINE__, "CURRENT");
184-
#line 91 "num_test.pgc"
195+
#line 102 "num_test.pgc"
185196

186197
if (sqlca.sqlcode < 0) sqlprint ( );}
187-
#line 91 "num_test.pgc"
198+
#line 102 "num_test.pgc"
188199

189200

190201
return 0;

src/interfaces/ecpg/test/expected/pgtypeslib-num_test.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
[NO_PID]: sqlca: code: 0, state: 00000
2727
[NO_PID]: ecpg_get_data on line 61: RESULT: 2369.7000000 offset: -1; array: no
2828
[NO_PID]: sqlca: code: 0, state: 00000
29-
[NO_PID]: ECPGtrans on line 90: action "rollback"; connection "ecpg1_regression"
29+
[NO_PID]: ECPGtrans on line 101: action "rollback"; connection "ecpg1_regression"
3030
[NO_PID]: sqlca: code: 0, state: 00000
3131
[NO_PID]: ecpg_finish: connection ecpg1_regression closed
3232
[NO_PID]: sqlca: code: 0, state: 00000

src/interfaces/ecpg/test/expected/pgtypeslib-num_test.stdout

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,5 @@ sub = 2369.7
44
mul = 13306998429.873000000
55
div = 1330699.84298730000 1.3307e+06
66
to long(0) = 20000000 14
7+
min int = -2147483648
8+
max int = 2147483647

src/interfaces/ecpg/test/pgtypeslib/num_test.pgc

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ main(void)
1919
exec sql end declare section;
2020
double d;
2121
long l1, l2;
22-
int i;
22+
int i, min, max;
2323

2424
ECPGdebug(1, stderr);
2525
exec sql whenever sqlerror do sqlprint();
@@ -87,6 +87,17 @@ main(void)
8787
PGTYPESnumeric_free(value2);
8888
PGTYPESnumeric_free(res);
8989

90+
/* check conversion of numeric to int */
91+
value1 = PGTYPESnumeric_from_asc("-2147483648", NULL);
92+
PGTYPESnumeric_to_int(value1, &min);
93+
printf("min int = %d\n", min);
94+
PGTYPESnumeric_free(value1);
95+
96+
value2 = PGTYPESnumeric_from_asc("2147483647", NULL);
97+
PGTYPESnumeric_to_int(value2, &max);
98+
printf("max int = %d\n", max);
99+
PGTYPESnumeric_free(value2);
100+
90101
exec sql rollback;
91102
exec sql disconnect;
92103

0 commit comments

Comments
 (0)