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:34:33 +0000 (16:34 -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 27534872dee311f2185146103923192f7eede2ef..41a5032c5e11231cd65c6db0c16d0a9ca0e76916 100644 (file)
@@ -8575,7 +8575,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</>).
+        architecture (<literal>INT_MIN .. INT_MAX</>).
        </para>
       </listitem>
      </varlistentry>
index a93d074de211bc5e9cbae519695ba1e9c6db35e8..c9c1a3896d3b40a4d503eb8262952cc5667024fe 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 6dad1dc4e4d117e2db4aa6610a0a6cbda398d6b0..0da155dfd8e544891ec304e4215bed58bd1fa765 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 0b5de558eba46293a6d66dbe6b6b18a59866898d..94379cfbf024a6cc6a780fad43083be027edf98f 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;