Changeset: aa184c4c8c65 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=aa184c4c8c65
Modified Files:
        sql/server/sql_datetime.c
        sql/test/SQLancer/Tests/sqlancer03.stable.err
        sql/test/SQLancer/Tests/sqlancer03.stable.out
Branch: Jun2020
Log Message:

Fix for SQLancer assertion error, check for overflow while converting a string 
to an interval type


diffs (156 lines):

diff --git a/sql/server/sql_datetime.c b/sql/server/sql_datetime.c
--- a/sql/server/sql_datetime.c
+++ b/sql/server/sql_datetime.c
@@ -55,7 +55,6 @@ qualifier2multiplier( int sk )
                /* fall through */
        case imonth:
                break;
-
        case iday:
                mul *= 24;
                /* fall through */
@@ -76,11 +75,9 @@ qualifier2multiplier( int sk )
 static int
 parse_interval_(mvc *sql, lng sign, char *str, int sk, int ek, int sp, int ep, 
lng *i)
 {
-       char *n = NULL;
-       lng val = 0;
-       char sep = ':';
+       char *n = NULL, sep = ':';
+       lng val = 0, mul;
        int type;
-       lng mul;
 
        if (*str == '-') {
                sign *= -1;
@@ -96,7 +93,6 @@ parse_interval_(mvc *sql, lng sign, char
                sep = '-';
                type = 0;
                break;
-
        case iday:
                mul *= 24;
                sep = ' ';
@@ -110,7 +106,6 @@ parse_interval_(mvc *sql, lng sign, char
        case isec:
                type = 1;
                break;
-
        default:
                if (sql)
                        snprintf(sql->errstr, ERRSIZE, _("Internal error: 
parse_interval: bad value for sk (%d)\n"), sk);
@@ -177,14 +172,14 @@ parse_interval_(mvc *sql, lng sign, char
        }
 }
 
+#define MABS(a) (((a) < 0) ? -(a) : (a))
+
 int
 parse_interval(mvc *sql, lng sign, char *str, int sk, int ek, int sp, int ep, 
lng *i)
 {
-       char *n = NULL;
-       lng val = 0;
-       char sep = ':';
+       char *n = NULL, sep = ':';
+       lng val = 0, mul, msec = 0;
        int type;
-       lng mul;
 
        if (*str == '-') {
                sign *= -1;
@@ -200,7 +195,6 @@ parse_interval(mvc *sql, lng sign, char 
                sep = '-';
                type = 0;
                break;
-
        case iday:
                mul *= 24;
                sep = ' ';
@@ -214,7 +208,6 @@ parse_interval(mvc *sql, lng sign, char 
        case isec:
                type = 1;
                break;
-
        default:
                if (sql)
                        snprintf(sql->errstr, ERRSIZE, _("Internal error: 
parse_interval: bad value for sk (%d)\n"), sk);
@@ -225,7 +218,6 @@ parse_interval(mvc *sql, lng sign, char 
        if (!n)
                return -1;
        if (sk == isec) {
-               lng msec = 0;
                if (n && n[0] == '.') {
                        char *nn;
                        msec = strtol(n+1, &nn, 10);
@@ -238,14 +230,36 @@ parse_interval(mvc *sql, lng sign, char 
                                n = nn;
                        }
                }
-               if (val > GDK_lng_max / 1000 ||
-                   (val == GDK_lng_max / 1000 && msec > GDK_lng_max % 1000)) {
+       }
+       switch (sk) {
+       case iyear:
+       case imonth:
+               if (val > (lng) GDK_int_max / MABS(mul)) {
+                       if (sql)
+                               snprintf(sql->errstr, ERRSIZE, _("Overflow\n"));
+                       return -1;
+               }
+               break;
+       case iday:
+       case ihour:
+       case imin:
+               if (val > GDK_lng_max / MABS(mul)) {
+                       if (sql)
+                               snprintf(sql->errstr, ERRSIZE, _("Overflow\n"));
+                       return -1;
+               }
+               break;
+       case isec:
+               if (val > GDK_lng_max / 1000 / MABS(mul) || (val == GDK_lng_max 
/ 1000 / MABS(mul) && msec > GDK_lng_max % 1000)) {
                        if (sql)
                                snprintf(sql->errstr, ERRSIZE, _("Overflow\n"));
                        return -1;
                }
                val *= 1000;
                val += msec;
+               break;
+       default:
+               assert(0);
        }
        val *= mul;
        *i += val;
diff --git a/sql/test/SQLancer/Tests/sqlancer03.stable.err 
b/sql/test/SQLancer/Tests/sqlancer03.stable.err
--- a/sql/test/SQLancer/Tests/sqlancer03.stable.err
+++ b/sql/test/SQLancer/Tests/sqlancer03.stable.err
@@ -5,6 +5,10 @@ stderr of test 'sqlancer03` in directory
 # 17:14:16 >  "mclient" "-lsql" "-ftest" "-tnone" "-Eutf-8" "-i" "-e" 
"--host=/var/tmp/mtest-439482" "--port=37916"
 # 17:14:16 >  
 
+MAPI  = (monetdb) /var/tmp/mtest-279965/.s.monetdb.34039
+QUERY = select all sum(all cast("concat"(cast("month"(t1.c0) as string), 
r'1313451898') as interval month)) from t1;
+ERROR = !Wrong format (11313451898)
+CODE  = 42000
 
 # 17:14:16 >  
 # 17:14:16 >  "Done."
diff --git a/sql/test/SQLancer/Tests/sqlancer03.stable.out 
b/sql/test/SQLancer/Tests/sqlancer03.stable.out
--- a/sql/test/SQLancer/Tests/sqlancer03.stable.out
+++ b/sql/test/SQLancer/Tests/sqlancer03.stable.out
@@ -469,6 +469,15 @@ stdout of test 'sqlancer03` in directory
 % clob # type
 % 0 # length
 #ROLLBACK;
+#START TRANSACTION;
+#CREATE TABLE "sys"."t1" ("c0" TIMESTAMP);
+#COPY 4 RECORDS INTO "sys"."t1" FROM stdin USING DELIMITERS E'\t',E'\n','"';
+#"1970-01-14 14:26:27.000000"
+#"1970-01-18 02:50:56.000000"
+#"1970-01-06 21:36:37.000000"
+#"1970-01-14 01:01:12.000000"
+[ 4    ]
+#ROLLBACK;
 #START TRANSACTION; -- Bug 6924
 #CREATE TABLE "sys"."t0" ("a" INTEGER, "b" INTEGER NOT NULL, CONSTRAINT 
"t0_a_b_unique" UNIQUE ("a","b"));
 #COPY 39 RECORDS INTO "sys"."t0" FROM stdin USING DELIMITERS E'\t',E'\n','"';
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to