Changeset: 7b9d7afdeb09 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=7b9d7afdeb09
Modified Files:
        gdk/gdk_heap.c
        monetdb5/mal/mal_runtime.c
        monetdb5/modules/atoms/uuid.c
        monetdb5/modules/mal/mkey.c
        sql/common/sql_list.c
        sql/server/sql_datetime.c
        sql/server/sql_decimal.c
        sql/test/pg_regress/Tests/interval.stable.err
        sql/test/pg_regress/Tests/interval.stable.err.int128
        sql/test/pg_regress/Tests/interval.stable.out
        sql/test/pg_regress/Tests/interval.stable.out.int128
Branch: Jun2016
Log Message:

Avoid undefined behavior in C: more overflow checking.


diffs (truncated from 400 to 300 lines):

diff --git a/gdk/gdk_heap.c b/gdk/gdk_heap.c
--- a/gdk/gdk_heap.c
+++ b/gdk/gdk_heap.c
@@ -757,7 +757,7 @@ HEAPwarm(Heap *h)
                int *lim = (int *) (h->base + h->free) - 4096;
 
                for (; cur < lim; cur += 4096)  /* try to schedule 4 parallel 
memory accesses */
-                       bogus_result += cur[0] + cur[1024] + cur[2048] + 
cur[3072];
+                       bogus_result |= cur[0] | cur[1024] | cur[2048] | 
cur[3072];
        }
        return bogus_result;
 }
diff --git a/monetdb5/mal/mal_runtime.c b/monetdb5/mal/mal_runtime.c
--- a/monetdb5/mal/mal_runtime.c
+++ b/monetdb5/mal/mal_runtime.c
@@ -250,8 +250,11 @@ lng getVolume(MalStkPtr stk, InstrPtr pc
        for (; i < limit; i++) {
                if (stk->stk[getArg(pci, i)].vtype == TYPE_bat) {
                        oid cnt = 0;
+                       bat bt;
 
-                       b = BBPquickdesc(abs(stk->stk[getArg(pci, 
i)].val.bval), TRUE);
+                       if ((bt = stk->stk[getArg(pci, i)].val.bval) == bat_nil)
+                               continue;
+                       b = BBPquickdesc(abs(bt), TRUE);
                        if (b == NULL)
                                continue;
                        cnt = BATcount(b);
diff --git a/monetdb5/modules/atoms/uuid.c b/monetdb5/modules/atoms/uuid.c
--- a/monetdb5/modules/atoms/uuid.c
+++ b/monetdb5/modules/atoms/uuid.c
@@ -231,10 +231,14 @@ UUIDhash(const void *v)
        const uuid *u = (const uuid *) v;
        unsigned int u1, u2, u3, u4;
 
-       u1 = u->u[0] << 24 | u->u[1] << 16 | u->u[2] << 8 | u->u[3];
-       u2 = u->u[4] << 24 | u->u[5] << 16 | u->u[6] << 8 | u->u[7];
-       u3 = u->u[8] << 24 | u->u[9] << 16 | u->u[10] << 8 | u->u[11];
-       u4 = u->u[12] << 24 | u->u[13] << 16 | u->u[14] << 8 | u->u[15];
+       u1 = (unsigned int) u->u[0] << 24 | (unsigned int) u->u[1] << 16 |
+               (unsigned int) u->u[2] << 8 | (unsigned int) u->u[3];
+       u2 = (unsigned int) u->u[4] << 24 | (unsigned int) u->u[5] << 16 |
+               (unsigned int) u->u[6] << 8 | (unsigned int) u->u[7];
+       u3 = (unsigned int) u->u[8] << 24 | (unsigned int) u->u[9] << 16 |
+               (unsigned int) u->u[10] << 8 | (unsigned int) u->u[11];
+       u4 = (unsigned int) u->u[12] << 24 | (unsigned int) u->u[13] << 16 |
+               (unsigned int) u->u[14] << 8 | (unsigned int) u->u[15];
        return (BUN) mix_int(u1 ^ u2 ^ u3 ^ u4);
 }
 
diff --git a/monetdb5/modules/mal/mkey.c b/monetdb5/modules/mal/mkey.c
--- a/monetdb5/modules/mal/mkey.c
+++ b/monetdb5/modules/mal/mkey.c
@@ -34,6 +34,14 @@
 #endif
 #endif
 
+#undef GDK_ROTATE
+
+static inline wrd
+GDK_ROTATE(wrd x, int y, int z, wrd m)
+{
+       return ((wrd) ((ulng) x << y) & ~m) | ((x >> z) & m);
+}
+
 /* TODO: nil handling. however; we do not want to lose time in 
bulk_rotate_xor_hash with that */
 str
 MKEYrotate(wrd *res, const wrd *val, const int *n)
diff --git a/sql/common/sql_list.c b/sql/common/sql_list.c
--- a/sql/common/sql_list.c
+++ b/sql/common/sql_list.c
@@ -331,7 +331,7 @@ int
 list_match(list *l1, list *l2, fcmp cmp)
 {
        node *n, *m;
-       int chk = 0;
+       ulng chk = 0;
 
        if (l1 == l2)
                return 0;
@@ -342,8 +342,9 @@ list_match(list *l1, list *l2, fcmp cmp)
        for (n = l1->h; n; n = n->next) {
                int pos = 0, fnd = 0;
                for (m = l2->h; m; m = m->next, pos++) {
-                       if (!(chk&(1<<pos)) && cmp(n->data, m->data) == 0) {
-                               chk &= 1<<pos;
+                       if (!(chk & ((ulng) 1 << pos)) &&
+                           cmp(n->data, m->data) == 0) {
+                               chk |= (ulng) 1 << pos;
                                fnd = 1;
                        }
                }
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
@@ -227,7 +227,6 @@ parse_interval(mvc *sql, lng sign, char 
                return -1;
        if (sk == isec) {
                int msec = 0;
-               val *= 1000;
                if (n && n[0] == '.') {
                        char *nn;
                        msec = strtol(n+1, &nn, 10);
@@ -240,6 +239,13 @@ 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)) {
+                       if (sql)
+                               snprintf(sql->errstr, ERRSIZE, _("Overflow\n"));
+                       return -1;
+               }
+               val *= 1000;
                val += msec;
        }
        val *= mul;
diff --git a/sql/server/sql_decimal.c b/sql/server/sql_decimal.c
--- a/sql/server/sql_decimal.c
+++ b/sql/server/sql_decimal.c
@@ -19,8 +19,10 @@ decimal_from_str(char *dec, char **end)
 {
 #ifdef HAVE_HGE
        hge res = 0;
+       const hge max0 = GDK_hge_max / 10, max1 = GDK_hge_max % 10;
 #else
        lng res = 0;
+       const lng max0 = GDK_lng_max / 10, max1 = GDK_lng_max % 10;
 #endif
        int neg = 0;
 
@@ -29,13 +31,13 @@ decimal_from_str(char *dec, char **end)
        if (*dec == '-') {
                neg = 1;
                dec++;
-       }
-       if (*dec == '+') {
-               neg = 0;
+       } else if (*dec == '+') {
                dec++;
        }
        for (; *dec && ((*dec >= '0' && *dec <= '9') || *dec == '.'); dec++) {
                if (*dec != '.') {
+                       if (res > max0 || (res == max0 && *dec - '0' > max1))
+                               break;
                        res *= 10;
                        res += *dec - '0';
                }
diff --git a/sql/test/pg_regress/Tests/interval.stable.err 
b/sql/test/pg_regress/Tests/interval.stable.err
--- a/sql/test/pg_regress/Tests/interval.stable.err
+++ b/sql/test/pg_regress/Tests/interval.stable.err
@@ -48,7 +48,16 @@ ERROR = !wrong format (-1 days +02:03)
 MAPI  = (monetdb) /var/tmp/mtest-21889/.s.monetdb.34286
 QUERY = SELECT cast('10 years -11 month -12 days +13:14' as interval second) 
AS "9 years...";
 ERROR = !wrong format (10 years -11 month -12 days +13:14)
-MAPI  = (monetdb) /var/tmp/mtest-21889/.s.monetdb.34286
+MAPI  = (monetdb) /var/tmp/mtest-13206/.s.monetdb.35665
+QUERY = INSERT INTO INTERVAL_TBL (f1) VALUES ('123456789012345678');
+ERROR = !wrong format (123456789012345678)
+MAPI  = (monetdb) /var/tmp/mtest-13206/.s.monetdb.35665
+QUERY = INSERT INTO INTERVAL_TBL (f1) VALUES ('1234567890123456789');
+ERROR = !wrong format (1234567890123456789)
+MAPI  = (monetdb) /var/tmp/mtest-13206/.s.monetdb.35665
+QUERY = INSERT INTO INTERVAL_TBL (f1) VALUES ('12345678901234567890');
+ERROR = !wrong format (12345678901234567890)
+MAPI  = (monetdb) /var/tmp/mtest-13206/.s.monetdb.35665
 QUERY = INSERT INTO INTERVAL_TBL (f1) VALUES ('1 day 2 hours 3 minutes 4 
seconds');
 ERROR = !wrong format (1 day 2 hours 3 minutes 4 seconds)
 MAPI  = (monetdb) /var/tmp/mtest-21889/.s.monetdb.34286
@@ -114,10 +123,7 @@ ERROR = !types sec_interval(13,0) and do
 MAPI  = (monetdb) /var/tmp/mtest-21889/.s.monetdb.34286
 QUERY = select avg(cast(f1 as double)) from interval_tbl;
 ERROR = !types sec_interval(13,0) and double(53,0) are not equal for column 
'f1'
-MAPI  = (monetdb) /var/tmp/mtest-11560/.s.monetdb.36606
-QUERY = select avg(cast(f1 as decimal)) from interval_tbl;
-ERROR = !too many digits (22 > 18)
-MAPI  = (monetdb) /var/tmp/mtest-11560/.s.monetdb.36606
+MAPI  = (monetdb) /var/tmp/mtest-8432/.s.monetdb.36662
 QUERY = select avg(cast(f1 as decimal(22,3))) from interval_tbl;
 ERROR = !decimal(22,3) isn't supported because P=22 > 18 in: "select 
avg(cast(f1 as decimal(22,3)"
         !syntax error, unexpected ')' in: ")"
diff --git a/sql/test/pg_regress/Tests/interval.stable.err.int128 
b/sql/test/pg_regress/Tests/interval.stable.err.int128
--- a/sql/test/pg_regress/Tests/interval.stable.err.int128
+++ b/sql/test/pg_regress/Tests/interval.stable.err.int128
@@ -48,7 +48,16 @@ ERROR = !wrong format (-1 days +02:03)
 MAPI  = (monetdb) /var/tmp/mtest-21889/.s.monetdb.34286
 QUERY = SELECT cast('10 years -11 month -12 days +13:14' as interval second) 
AS "9 years...";
 ERROR = !wrong format (10 years -11 month -12 days +13:14)
-MAPI  = (monetdb) /var/tmp/mtest-21889/.s.monetdb.34286
+MAPI  = (monetdb) /var/tmp/mtest-13206/.s.monetdb.35665
+QUERY = INSERT INTO INTERVAL_TBL (f1) VALUES ('123456789012345678');
+ERROR = !wrong format (123456789012345678)
+MAPI  = (monetdb) /var/tmp/mtest-13206/.s.monetdb.35665
+QUERY = INSERT INTO INTERVAL_TBL (f1) VALUES ('1234567890123456789');
+ERROR = !wrong format (1234567890123456789)
+MAPI  = (monetdb) /var/tmp/mtest-13206/.s.monetdb.35665
+QUERY = INSERT INTO INTERVAL_TBL (f1) VALUES ('12345678901234567890');
+ERROR = !wrong format (12345678901234567890)
+MAPI  = (monetdb) /var/tmp/mtest-13206/.s.monetdb.35665
 QUERY = INSERT INTO INTERVAL_TBL (f1) VALUES ('1 day 2 hours 3 minutes 4 
seconds');
 ERROR = !wrong format (1 day 2 hours 3 minutes 4 seconds)
 MAPI  = (monetdb) /var/tmp/mtest-21889/.s.monetdb.34286
@@ -114,9 +123,6 @@ ERROR = !types sec_interval(13,0) and do
 MAPI  = (monetdb) /var/tmp/mtest-21889/.s.monetdb.34286
 QUERY = select avg(cast(f1 as double)) from interval_tbl;
 ERROR = !types sec_interval(13,0) and double(53,0) are not equal for column 
'f1'
-MAPI  = (monetdb) /var/tmp/mtest-21889/.s.monetdb.34286
-QUERY = select avg(cast(f1 as decimal)) from interval_tbl;
-ERROR = !too many digits (22 > 18)
 
 # 15:52:24 >  
 # 15:52:24 >  "Done."
diff --git a/sql/test/pg_regress/Tests/interval.stable.out 
b/sql/test/pg_regress/Tests/interval.stable.out
--- a/sql/test/pg_regress/Tests/interval.stable.out
+++ b/sql/test/pg_regress/Tests/interval.stable.out
@@ -36,22 +36,13 @@ Ready.
 [ 1    ]
 #INSERT INTO INTERVAL_TBL (f1) VALUES (60 * 60 * 24 * 365 * 2014);
 [ 1    ]
-#INSERT INTO INTERVAL_TBL (f1) VALUES ('@ 34 year');
-[ 1    ]
-#INSERT INTO INTERVAL_TBL (f1) VALUES ('@ 3 months');
-[ 1    ]
-#INSERT INTO INTERVAL_TBL (f1) VALUES ('12345678901234567890');
-[ 1    ]
 #SELECT '' AS ten, INTERVAL_TBL.* FROM INTERVAL_TBL;
 % .L,  sys.interval_tbl # table_name
 % ten, f1 # name
 % char,        sec_interval # type
-% 0,   21 # length
+% 0,   15 # length
 [ "",  1.234   ]
 [ "",  63513504000.000 ]
-[ "",  -5670419503621183.312   ]
-[ "",  -1363962815083169.272   ]
-[ "",  -1.000  ]
 #SELECT '' AS fortyfive, r1.*, r2.*
 #   FROM INTERVAL_TBL r1, INTERVAL_TBL r2
 #   WHERE r1.f1 > r2.f1
@@ -59,33 +50,27 @@ Ready.
 % .L,  sys.r1, sys.r2 # table_name
 % fortyfive,   f1,     f1 # name
 % char,        sec_interval,   sec_interval # type
-% 0,   21,     21 # length
-[ "",  -1363962815083169.272,  -5670419503621183.312   ]
-[ "",  -1.000, -5670419503621183.312   ]
-[ "",  -1.000, -1363962815083169.272   ]
-[ "",  1.234,  -5670419503621183.312   ]
-[ "",  1.234,  -1363962815083169.272   ]
-[ "",  1.234,  -1.000  ]
-[ "",  63513504000.000,        -5670419503621183.312   ]
-[ "",  63513504000.000,        -1363962815083169.272   ]
-[ "",  63513504000.000,        -1.000  ]
+% 0,   15,     5 # length
 [ "",  63513504000.000,        1.234   ]
 #SELECT '' AS ten, INTERVAL_TBL.* FROM INTERVAL_TBL order by f1 desc;
 % .L,  sys.interval_tbl # table_name
 % ten, f1 # name
 % char,        sec_interval # type
-% 0,   21 # length
+% 0,   15 # length
 [ "",  63513504000.000 ]
 [ "",  1.234   ]
-[ "",  -1.000  ]
-[ "",  -1363962815083169.272   ]
-[ "",  -5670419503621183.312   ]
+#select avg(cast(f1 as decimal)) from interval_tbl;
+% sys.L2 # table_name
+% L2 # name
+% double # type
+% 24 # length
+[ 3.1756752e+13        ]
 #select min(f1) from interval_tbl;
 % sys.L1 # table_name
 % L1 # name
 % sec_interval # type
-% 21 # length
-[ -5670419503621183.312        ]
+% 5 # length
+[ 1.234        ]
 #select max(f1) from interval_tbl;
 % sys.L1 # table_name
 % L1 # name
@@ -97,13 +82,13 @@ Ready.
 % L1 # name
 % wrd # type
 % 1 # length
-[ 5    ]
+[ 2    ]
 #select count(distinct f1) from interval_tbl;
 % sys.L1 # table_name
 % L1 # name
 % wrd # type
 % 1 # length
-[ 5    ]
+[ 2    ]
 #DROP TABLE INTERVAL_TBL;
 
 # 12:56:40 >  
diff --git a/sql/test/pg_regress/Tests/interval.stable.out.int128 
b/sql/test/pg_regress/Tests/interval.stable.out.int128
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to