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