Skip to content

Commit c7181a3

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 02ef4d1 commit c7181a3

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
@@ -8618,7 +8618,7 @@ int dectoint(decimal *np, int *ip);
86188618
Note that the ECPG implementation differs from the <productname>Informix</productname>
86198619
implementation. <productname>Informix</productname> limits an integer to the range from -32767 to
86208620
32767, while the limits in the ECPG implementation depend on the
8621-
architecture (<literal>-INT_MAX .. INT_MAX</literal>).
8621+
architecture (<literal>INT_MIN .. INT_MAX</literal>).
86228622
</para>
86238623
</listitem>
86248624
</varlistentry>

src/interfaces/ecpg/pgtypeslib/numeric.c

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

1589-
if (l < -INT_MAX || l > INT_MAX)
1589+
/* silence compilers that might complain about useless tests */
1590+
#if SIZEOF_LONG > SIZEOF_INT
1591+
1592+
if (l < INT_MIN || l > INT_MAX)
15901593
{
15911594
errno = PGTYPES_NUM_OVERFLOW;
15921595
return -1;
15931596
}
15941597

1598+
#endif
1599+
15951600
*ip = (int) l;
15961601
return 0;
15971602
}

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

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

4848
double d;
4949
long l1, l2;
50-
int i;
50+
int i, min, max;
5151

5252
ECPGdebug(1, stderr);
5353
/* exec sql whenever sqlerror do sqlprint ( ) ; */
@@ -144,17 +144,28 @@ if (sqlca.sqlcode < 0) sqlprint ( );}
144144
PGTYPESnumeric_free(value2);
145145
PGTYPESnumeric_free(res);
146146

147+
/* check conversion of numeric to int */
148+
value1 = PGTYPESnumeric_from_asc("-2147483648", NULL);
149+
PGTYPESnumeric_to_int(value1, &min);
150+
printf("min int = %d\n", min);
151+
PGTYPESnumeric_free(value1);
152+
153+
value2 = PGTYPESnumeric_from_asc("2147483647", NULL);
154+
PGTYPESnumeric_to_int(value2, &max);
155+
printf("max int = %d\n", max);
156+
PGTYPESnumeric_free(value2);
157+
147158
{ ECPGtrans(__LINE__, NULL, "rollback");
148-
#line 93 "num_test.pgc"
159+
#line 104 "num_test.pgc"
149160

150161
if (sqlca.sqlcode < 0) sqlprint ( );}
151-
#line 93 "num_test.pgc"
162+
#line 104 "num_test.pgc"
152163

153164
{ ECPGdisconnect(__LINE__, "CURRENT");
154-
#line 94 "num_test.pgc"
165+
#line 105 "num_test.pgc"
155166

156167
if (sqlca.sqlcode < 0) sqlprint ( );}
157-
#line 94 "num_test.pgc"
168+
#line 105 "num_test.pgc"
158169

159170

160171
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 66: RESULT: 2369.7000000 offset: -1; array: no
2828
[NO_PID]: sqlca: code: 0, state: 00000
29-
[NO_PID]: ECPGtrans on line 93: action "rollback"; connection "ecpg1_regression"
29+
[NO_PID]: ECPGtrans on line 104: 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.330700e+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
@@ -24,7 +24,7 @@ main(void)
2424
exec sql end declare section;
2525
double d;
2626
long l1, l2;
27-
int i;
27+
int i, min, max;
2828

2929
ECPGdebug(1, stderr);
3030
exec sql whenever sqlerror do sqlprint();
@@ -90,6 +90,17 @@ main(void)
9090
PGTYPESnumeric_free(value2);
9191
PGTYPESnumeric_free(res);
9292

93+
/* check conversion of numeric to int */
94+
value1 = PGTYPESnumeric_from_asc("-2147483648", NULL);
95+
PGTYPESnumeric_to_int(value1, &min);
96+
printf("min int = %d\n", min);
97+
PGTYPESnumeric_free(value1);
98+
99+
value2 = PGTYPESnumeric_from_asc("2147483647", NULL);
100+
PGTYPESnumeric_to_int(value2, &max);
101+
printf("max int = %d\n", max);
102+
PGTYPESnumeric_free(value2);
103+
93104
exec sql rollback;
94105
exec sql disconnect;
95106

0 commit comments

Comments
 (0)