Changeset: ee6e0204f284 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=ee6e0204f284
Modified Files:
        sql/backends/monet5/sql_time.c
Branch: default
Log Message:

Test for overflows in conversions to interval types


diffs (155 lines):

diff --git a/sql/backends/monet5/sql_time.c b/sql/backends/monet5/sql_time.c
--- a/sql/backends/monet5/sql_time.c
+++ b/sql/backends/monet5/sql_time.c
@@ -884,30 +884,66 @@ bailout:
        return msg;
 }
 
-#define interval_loop(FUNC, TPE) \
+#define interval_loop(FUNC, TPE, FUNC_NAME, MAX_VALUE, CAST_VALIDATION, 
MUL_VALIDATION) \
        do { \
                if (is_a_bat) { \
                        TPE *restrict vals = Tloc(b, 0); \
-                       for (BUN i = 0 ; i < q ; i++) \
-                               FUNC(ret[i], TPE, vals[i]); \
+                       for (BUN i = 0 ; i < q && !msg ; i++) \
+                               FUNC(ret[i], vals[i], TPE, FUNC_NAME, 
MAX_VALUE, CAST_VALIDATION, MUL_VALIDATION); \
                } else { \
                        TPE val = *(TPE*)getArgReference(stk, pci, 1); \
-                       FUNC(*ret, TPE, val); \
+                       FUNC(*ret, val, TPE, FUNC_NAME, MAX_VALUE, 
CAST_VALIDATION, MUL_VALIDATION); \
                } \
        } while(0)
 
-#define month_interval_convert(OUT, TPE, IN) \
+#define month_interval_convert(OUT, IN, TPE, FUNC_NAME, MAX_VALUE, 
CAST_VALIDATION, MUL_VALIDATION) \
        do { \
                if (is_##TPE##_nil(IN)) { \
                        OUT = int_nil; \
                        hasnil = 1; \
                } else { \
-                       int r = (int) IN; \
-                       r *= multiplier; \
+                       TPE next = IN; \
+                       int cast, r; \
+                       CAST_VALIDATION(TPE, FUNC_NAME, MAX_VALUE); \
+                       cast = (int) next; \
+                       r = cast * multiplier; \
+                       MUL_VALIDATION(TPE, FUNC_NAME, MAX_VALUE); \
                        OUT = r; \
                } \
        } while (0)
 
+#define DO_NOTHING(TPE, FUNC_NAME, MAX_VALUE) ;
+
+#define CAST_VALIDATION(TPE, FUNC_NAME, MAX_VALUE) \
+       do { \
+               if (next > (TPE) MAX_VALUE) { \
+                       size_t len = 0; \
+                       char *str_val = NULL; \
+                       if (BATatoms[tpe].atomToStr(&str_val, &len, &next, 
false) < 0) { \
+                               msg = createException(SQL, "batcalc." 
FUNC_NAME, SQLSTATE(HY013) MAL_MALLOC_FAIL); \
+                               goto bailout; \
+                       } \
+                       msg = createException(SQL, "batcalc." FUNC_NAME, 
SQLSTATE(22003) "Value %s too large to fit at a " FUNC_NAME, str_val); \
+                       GDKfree(str_val); \
+                       goto bailout; \
+               } \
+       } while (0)
+
+#define MUL_OVERFLOW(TPE, FUNC_NAME, MAX_VALUE) /* MAX_VALUE is ignored on 
this macro */ \
+       do { \
+               if (r < cast) { \
+                       size_t len = 0; \
+                       char *str_val = NULL; \
+                       if (BATatoms[tpe].atomToStr(&str_val, &len, &cast, 
false) < 0) { \
+                               msg = createException(SQL, "batcalc." 
FUNC_NAME, SQLSTATE(HY013) MAL_MALLOC_FAIL); \
+                               goto bailout; \
+                       } \
+                       msg = createException(SQL, "batcalc." FUNC_NAME, 
SQLSTATE(22003) "Overflow in convertion of %s to " FUNC_NAME, str_val); \
+                       GDKfree(str_val); \
+                       goto bailout; \
+               } \
+       } while (0)
+
 str
 month_interval(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
 {
@@ -953,20 +989,20 @@ month_interval(Client cntxt, MalBlkPtr m
 
        switch (tpe) {
        case TYPE_bte:
-               interval_loop(month_interval_convert, bte);
+               interval_loop(month_interval_convert, bte, "month_interval", 
GDK_int_max, DO_NOTHING, DO_NOTHING);
                break;
        case TYPE_sht:
-               interval_loop(month_interval_convert, sht);
+               interval_loop(month_interval_convert, sht, "month_interval", 
GDK_int_max, DO_NOTHING, DO_NOTHING);
                break;
        case TYPE_int:
-               interval_loop(month_interval_convert, int);
+               interval_loop(month_interval_convert, int, "month_interval", 
GDK_int_max, DO_NOTHING, MUL_OVERFLOW);
                break;
        case TYPE_lng:
-               interval_loop(month_interval_convert, lng);
+               interval_loop(month_interval_convert, lng, "month_interval", 
GDK_int_max, CAST_VALIDATION, MUL_OVERFLOW);
                break;
 #ifdef HAVE_HGE
        case TYPE_hge:
-               interval_loop(month_interval_convert, hge);
+               interval_loop(month_interval_convert, hge, "month_interval", 
GDK_int_max, CAST_VALIDATION, MUL_OVERFLOW);
                break;
 #endif
        default: {
@@ -990,18 +1026,22 @@ bailout:
        return msg;
 }
 
-#define second_interval_convert(OUT, TPE, IN) \
+#define second_interval_convert(OUT, IN, TPE, FUNC_NAME, MAX_VALUE, 
CAST_VALIDATION, MUL_VALIDATION) \
        do { \
                if (is_##TPE##_nil(IN)) { \
                        OUT = lng_nil; \
                        hasnil = 1; \
                } else { \
-                       lng r = (lng) IN; \
-                       r *= multiplier; \
+                       TPE next = IN; \
+                       lng cast, r; \
+                       CAST_VALIDATION(TPE, FUNC_NAME, MAX_VALUE); \
+                       cast = (lng) next; \
+                       r = cast * multiplier; \
                        if (scale) { \
                                r += shift; \
                                r /= divider; \
                        } \
+                       MUL_VALIDATION(TPE, FUNC_NAME, MAX_VALUE); \
                        OUT = r; \
                } \
        } while (0)
@@ -1073,20 +1113,20 @@ second_interval(Client cntxt, MalBlkPtr 
 
        switch (tpe) {
        case TYPE_bte:
-               interval_loop(second_interval_convert, bte);
+               interval_loop(second_interval_convert, bte, "sec_interval", 
GDK_lng_max, DO_NOTHING, MUL_OVERFLOW);
                break;
        case TYPE_sht:
-               interval_loop(second_interval_convert, sht);
+               interval_loop(second_interval_convert, sht, "sec_interval", 
GDK_lng_max, DO_NOTHING, MUL_OVERFLOW);
                break;
        case TYPE_int:
-               interval_loop(second_interval_convert, int);
+               interval_loop(second_interval_convert, int, "sec_interval", 
GDK_lng_max, DO_NOTHING, MUL_OVERFLOW);
                break;
        case TYPE_lng:
-               interval_loop(second_interval_convert, lng);
+               interval_loop(second_interval_convert, lng, "sec_interval", 
GDK_lng_max, DO_NOTHING, MUL_OVERFLOW);
                break;
 #ifdef HAVE_HGE
        case TYPE_hge:
-               interval_loop(second_interval_convert, hge);
+               interval_loop(second_interval_convert, hge, "sec_interval", 
GDK_lng_max, CAST_VALIDATION, MUL_OVERFLOW);
                break;
 #endif
        default: {
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to