Fix range check in ECPG numeric to int conversion
authorJohn Naylor <[email protected]>
Fri, 30 Jul 2021 17:50:23 +0000 (13:50 -0400)
committerJohn Naylor <[email protected]>
Fri, 30 Jul 2021 20:12:17 +0000 (16:12 -0400)
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
src/interfaces/ecpg/pgtypeslib/numeric.c
src/interfaces/ecpg/test/expected/pgtypeslib-num_test.c
src/interfaces/ecpg/test/expected/pgtypeslib-num_test.stderr
src/interfaces/ecpg/test/expected/pgtypeslib-num_test.stdout
src/interfaces/ecpg/test/pgtypeslib/num_test.pgc

index b4e69664057885dc3f7fa770d41bca23419c2ee5..e94073f461d93d12f3c0f9cef4ba2186dd637078 100644 (file)
@@ -8618,7 +8618,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>
index 6643242ab196ba98f5c2ad31d3ef88f353135a49..88a4302faa67049fea3a51fced0d6cfdd76c4708 100644 (file)
@@ -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;
 }
index 1b1239eacad48354f9a857a94abc3c350a270fa9..43d1e15c17cc6dfce74b503a29301d3406d40e4a 100644 (file)
@@ -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;
index d834c22aab9218b51016d99e529316a13574a148..c57fe8b7a907c6f9c3b7e8447e6d891c9e765c94 100644 (file)
@@ -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
index 52515ebde268e1c082f6e525a04d161036de6d24..459d4bffd837630901cba0548a2bbb5d12e6cbf7 100644 (file)
@@ -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
index 98912704947acb69e5bd39cd0c0efe462ce007e9..7bdd375df13996b337fdc5c29ea496609b0587e9 100644 (file)
@@ -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;