Skip to content

Commit 89f5a54

Browse files
author
Tor Didriksen
committed
Bug#27134148 UBSAN: DATE_ADD_INTERVAL - SIGNED INTEGER OVERFLOW
Post-push fix: add stricter checks for overflow when adding intervals of type year, quarter, ..., second, microsecond. Change-Id: I05237f8535392ecb0e3f86512c2e67eb171995e4 (cherry picked from commit 07a88b3c6a9a104502ac359ff2bf7567f2f0fd6f)
1 parent 618749e commit 89f5a54

File tree

5 files changed

+92
-14
lines changed

5 files changed

+92
-14
lines changed

mysql-test/r/func_time.result

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1971,18 +1971,23 @@ Warning 1441 Datetime function: datetime field overflow
19711971
SELECT
19721972
timestampadd(hour ,1.212208e+308,'1995-01-05 06:32:20.859724') as result;
19731973
result
1974-
1995-01-05 05:32:20.859724
1974+
NULL
1975+
Warnings:
1976+
Warning 1441 Datetime function: datetime field overflow
19751977
SELECT
19761978
timestampadd(minute ,1.212208e+308,'1995-01-05 06:32:20.859724') as result;
19771979
result
1978-
1995-01-05 06:31:20.859724
1980+
NULL
1981+
Warnings:
1982+
Warning 1441 Datetime function: datetime field overflow
19791983
SELECT
19801984
timestampadd(second ,1.212208e+308,'1995-01-05 06:32:20.859724') as result;
19811985
result
1982-
1995-01-05 06:32:20.859724
1986+
NULL
19831987
Warnings:
19841988
Warning 1292 Truncated incorrect DECIMAL value: '1.212208'
19851989
Warning 1292 Truncated incorrect DECIMAL value: '99999999999999999999999999999999999999999999999999999999999999999'
1990+
Warning 1441 Datetime function: date_add_interval field overflow
19861991
SELECT
19871992
timestampadd(microsecond ,1.212208e+308,'1995-01-05 06:32:20.859724') as result;
19881993
result
@@ -2018,12 +2023,49 @@ Warning 1441 Datetime function: date_add_interval field overflow
20182023
SELECT
20192024
date_add('1995-01-05', INTERVAL '9223372036854775808-02' SECOND) as result;
20202025
result
2021-
1995-01-05 00:00:00
2026+
NULL
20222027
Warnings:
20232028
Warning 1292 Truncated incorrect DECIMAL value: '9223372036854775808'
2029+
Warning 1441 Datetime function: date_add_interval field overflow
20242030
SELECT
20252031
date_add('1995-01-05', INTERVAL '9223372036854775700-02' YEAR_MONTH) as result;
20262032
result
20272033
NULL
20282034
Warnings:
20292035
Warning 1441 Datetime function: datetime field overflow
2036+
SELECT
2037+
date_add('1995-01-05', INTERVAL 9223372036854775806 SECOND) as result;
2038+
result
2039+
NULL
2040+
Warnings:
2041+
Warning 1441 Datetime function: datetime field overflow
2042+
SELECT
2043+
date_add('1995-01-05', INTERVAL 9223372036854775806 MINUTE) as result;
2044+
result
2045+
NULL
2046+
Warnings:
2047+
Warning 1441 Datetime function: datetime field overflow
2048+
SELECT
2049+
date_add('1995-01-05', INTERVAL 9223372036854775806 HOUR) as result;
2050+
result
2051+
NULL
2052+
Warnings:
2053+
Warning 1441 Datetime function: datetime field overflow
2054+
SELECT
2055+
date_add('1995-01-05', INTERVAL -9223372036854775806 SECOND) as result;
2056+
result
2057+
NULL
2058+
Warnings:
2059+
Warning 1441 Datetime function: datetime field overflow
2060+
SELECT
2061+
date_add('1995-01-05', INTERVAL -9223372036854775806 MINUTE) as result;
2062+
result
2063+
NULL
2064+
Warnings:
2065+
Warning 1441 Datetime function: datetime field overflow
2066+
SELECT
2067+
date_add('1995-01-05', INTERVAL -9223372036854775806 HOUR) as result;
2068+
result
2069+
NULL
2070+
Warnings:
2071+
Warning 1441 Datetime function: datetime field overflow

mysql-test/r/type_temporal_fractional.result

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5552,7 +5552,7 @@ Warnings:
55525552
Warning 1441 Datetime function: time field overflow
55535553
SELECT DATE_ADD(TIME'00:00:00.0', INTERVAL 1000000000000000000000.1 SECOND);
55545554
DATE_ADD(TIME'00:00:00.0', INTERVAL 1000000000000000000000.1 SECOND)
5555-
00:00:00.0
5555+
NULL
55565556
Warnings:
55575557
Warning 1292 Truncated incorrect DECIMAL value: '1000000000000000000000.1'
55585558
CREATE TABLE t1 AS SELECT

mysql-test/t/func_time.test

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1264,3 +1264,21 @@ date_add('1995-01-05', INTERVAL '9223372036854775808-02' SECOND) as result;
12641264

12651265
SELECT
12661266
date_add('1995-01-05', INTERVAL '9223372036854775700-02' YEAR_MONTH) as result;
1267+
1268+
SELECT
1269+
date_add('1995-01-05', INTERVAL 9223372036854775806 SECOND) as result;
1270+
1271+
SELECT
1272+
date_add('1995-01-05', INTERVAL 9223372036854775806 MINUTE) as result;
1273+
1274+
SELECT
1275+
date_add('1995-01-05', INTERVAL 9223372036854775806 HOUR) as result;
1276+
1277+
SELECT
1278+
date_add('1995-01-05', INTERVAL -9223372036854775806 SECOND) as result;
1279+
1280+
SELECT
1281+
date_add('1995-01-05', INTERVAL -9223372036854775806 MINUTE) as result;
1282+
1283+
SELECT
1284+
date_add('1995-01-05', INTERVAL -9223372036854775806 HOUR) as result;

sql/item_timefunc.cc

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1655,10 +1655,12 @@ bool get_interval_value(Item *args, interval_type int_type,
16551655
{
16561656
my_decimal decimal_value, *val;
16571657
lldiv_t tmp;
1658-
if (!(val= args->val_decimal(&decimal_value)) ||
1659-
my_decimal2lldiv_t(E_DEC_FATAL_ERROR, val, &tmp))
1660-
return false;
1661-
1658+
if (!(val= args->val_decimal(&decimal_value)))
1659+
return true;
1660+
int lldiv_result= my_decimal2lldiv_t(E_DEC_FATAL_ERROR, val, &tmp);
1661+
if (lldiv_result == E_DEC_OVERFLOW)
1662+
return true;
1663+
16621664
if (tmp.quot >= 0 && tmp.rem >= 0)
16631665
{
16641666
interval->neg= false;
@@ -1678,6 +1680,10 @@ bool get_interval_value(Item *args, interval_type int_type,
16781680
value= args->val_int();
16791681
if (args->null_value)
16801682
return true;
1683+
/*
1684+
Large floating-point values will be truncated to LLONG_MIN / LLONG_MAX
1685+
LLONG_MIN cannot be negated below, so reject it here.
1686+
*/
16811687
if (value == LLONG_MIN)
16821688
return true;
16831689
if (value < 0)

sql/sql_time.cc

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1388,7 +1388,7 @@ bool make_truncated_value_warning(THD *thd,
13881388

13891389

13901390
/* Daynumber from year 0 to 9999-12-31 */
1391-
#define MAX_DAY_NUMBER 3652424L
1391+
#define MAX_DAY_NUMBER 3652424UL
13921392

13931393
bool date_add_interval(MYSQL_TIME *ltime, interval_type int_type,
13941394
Interval interval)
@@ -1419,11 +1419,23 @@ bool date_add_interval(MYSQL_TIME *ltime, interval_type int_type,
14191419
extra_sec= microseconds/1000000L;
14201420
microseconds= microseconds%1000000L;
14211421

1422-
sec=((ltime->day-1)*3600*24L+ltime->hour*3600+ltime->minute*60+
1422+
if (interval.day > MAX_DAY_NUMBER)
1423+
goto invalid_date;
1424+
if (interval.hour > MAX_DAY_NUMBER * 24ULL)
1425+
goto invalid_date;
1426+
if (interval.minute > MAX_DAY_NUMBER * 24ULL * 60ULL)
1427+
goto invalid_date;
1428+
if (interval.second > MAX_DAY_NUMBER * 24ULL * 60ULL * 60ULL)
1429+
goto invalid_date;
1430+
sec=((ltime->day-1) * 3600LL * 24LL +
1431+
ltime->hour * 3600LL +
1432+
ltime->minute * 60LL +
14231433
ltime->second +
1424-
sign* (longlong) (interval.day*3600*24L +
1425-
interval.hour*3600LL+interval.minute*60LL+
1426-
interval.second))+ extra_sec;
1434+
sign* (longlong) (interval.day * 3600ULL * 24ULL +
1435+
interval.hour * 3600ULL +
1436+
interval.minute * 60ULL +
1437+
interval.second))
1438+
+ extra_sec;
14271439
if (microseconds < 0)
14281440
{
14291441
microseconds+= 1000000LL;

0 commit comments

Comments
 (0)