1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-07-30 19:23:07 +03:00

MCOL-1647 Fix TIME regressions

Fixes the following:

* Read past buffer end in intToDatetime / intToTime
* Allow intToTime to convert datetime
* Allow intToTime to convert shortened time values
* Allow stringToTime to convert datetime and int time values
* Fix saturation / bad values in intToTime and stringToTime
* Fix TIME return in STR_TO_DATE()
* Fix NULL return on type inequality for TIMEDIFF()
* Fix zero day calculation error in ADDTIME()/SUBTIME()
* Fix DATETIME to int calculation error in aggregate bit operations
* Make the new harderning flags optional with -DSECURITY_HARDENED_NEW
This commit is contained in:
Andrew Hutchings
2018-08-17 07:55:51 +01:00
parent 934667f02b
commit 580a3ec123
8 changed files with 122 additions and 39 deletions

View File

@ -2566,7 +2566,6 @@ int64_t DataConvert::intToDatetime(int64_t data, bool* date)
hour = string(buf + 8, 2);
min = string(buf + 10, 2);
sec = string(buf + 12, 2);
msec = string(buf + 14, 6);
break;
case 12:
@ -2576,7 +2575,6 @@ int64_t DataConvert::intToDatetime(int64_t data, bool* date)
hour = string(buf + 6, 2);
min = string(buf + 8, 2);
sec = string(buf + 10, 2);
msec = string(buf + 12, 6);
break;
case 10:
@ -2585,7 +2583,6 @@ int64_t DataConvert::intToDatetime(int64_t data, bool* date)
hour = string(buf + 4, 2);
min = string(buf + 6, 2);
sec = string(buf + 8, 2);
msec = string(buf + 10, 6);
break;
case 9:
@ -2594,7 +2591,6 @@ int64_t DataConvert::intToDatetime(int64_t data, bool* date)
hour = string(buf + 3, 2);
min = string(buf + 5, 2);
sec = string(buf + 7, 2);
msec = string(buf + 9, 6);
break;
case 8:
@ -2645,7 +2641,7 @@ int64_t DataConvert::intToDatetime(int64_t data, bool* date)
h = atoi(hour.c_str());
minute = atoi(min.c_str());
s = atoi(sec.c_str());
ms = atoi(msec.c_str());
ms = 0;
if (!isDateValid(d, m, y) || !isDateTimeValid(h, minute, s, ms))
return -1;
@ -2664,7 +2660,7 @@ int64_t DataConvert::intToDatetime(int64_t data, bool* date)
return *(reinterpret_cast<uint64_t*>(&adaytime));
}
int64_t DataConvert::intToTime(int64_t data)
int64_t DataConvert::intToTime(int64_t data, bool fromString)
{
char buf[21] = {0};
char* bufread = buf;
@ -2693,43 +2689,78 @@ int64_t DataConvert::intToTime(int64_t data)
bufread++;
}
bool zero = false;
switch (strlen(bufread))
{
// A full datetime
case 14:
hour = string(buf + 8, 2);
min = string(buf + 10, 2);
sec = string(buf + 12, 2);
break;
// Date so this is all 0
case 8:
zero = true;
break;
case 7:
hour = string(bufread, 3);
min = string(bufread + 2, 2);
sec = string(bufread + 4, 2);
msec = string(bufread + 6, 6);
break;
case 6:
hour = string(bufread, 2);
min = string(bufread + 2, 2);
sec = string(bufread + 4, 2);
msec = string(bufread + 6, 6);
break;
case 5:
hour = string(bufread, 1);
min = string(bufread + 1, 2);
sec = string(bufread + 3, 2);
break;
case 4:
min = string(bufread, 2);
sec = string(bufread + 2, 2);
msec = string(bufread + 4, 6);
break;
case 3:
min = string(bufread, 1);
sec = string(bufread + 1, 2);
break;
case 2:
sec = string(bufread, 2);
msec = string(bufread + 2, 6);
break;
case 1:
sec = string(bufread, 1);
break;
default:
return -1;
}
h = atoi(hour.c_str());
minute = atoi(min.c_str());
s = atoi(sec.c_str());
ms = atoi(msec.c_str());
if (!zero)
{
h = atoi(hour.c_str());
minute = atoi(min.c_str());
s = atoi(sec.c_str());
}
else if (fromString)
{
// Saturate fromString
h = 838;
minute = 59;
s = 59;
ms = 999999;
}
if (!isTimeValid(h, minute, s, ms))
if (!isTimeValid(h, minute, s, 0))
return -1;
atime.hour = h;
@ -2749,6 +2780,7 @@ int64_t DataConvert::stringToTime(const string& data)
uint64_t min = 0, sec = 0, msec = 0;
int64_t day = -1, hour = 0;
bool isNeg = false;
bool hasDate = false;
string time, hms, ms;
char* end = NULL;
@ -2760,18 +2792,27 @@ int64_t DataConvert::stringToTime(const string& data)
isNeg = true;
}
if (data.substr(pos+1, data.length()-pos-1).find("-") != string::npos)
{
// A second dash, this has a date
hasDate = true;
isNeg = false;
}
// Day
pos = data.find(" ");
if (pos != string::npos)
{
day = strtol(data.substr(0, pos).c_str(), &end, 10);
if (!hasDate)
{
day = strtol(data.substr(0, pos).c_str(), &end, 10);
if (*end != '\0')
return -1;
if (*end != '\0')
return -1;
hour = day * 24;
day = -1;
hour = day * 24;
day = -1;
}
time = data.substr(pos + 1, data.length() - pos - 1);
}
else
@ -2779,6 +2820,22 @@ int64_t DataConvert::stringToTime(const string& data)
time = data;
}
if (time.find(":") == string::npos)
{
if (hasDate)
{
// Has dashes, no colons. This is just a date!
// Or the length < 6 (MariaDB returns NULL)
return -1;
}
else
{
// This is an int time
return intToTime(atoll(time.c_str()), true);
}
}
// Fraction
pos = time.find(".");
@ -2797,11 +2854,18 @@ int64_t DataConvert::stringToTime(const string& data)
if (pos == string::npos)
{
hour += atoi(hms.c_str());
if (hour >= 0)
hour += atoi(hms.c_str());
else
hour -= atoi(hms.c_str());
}
else
{
hour += atoi(hms.substr(0, pos).c_str());
if (hour >= 0)
hour += atoi(hms.substr(0, pos).c_str());
else
hour -= atoi(hms.substr(0, pos).c_str());
ms = hms.substr(pos + 1, hms.length() - pos - 1);
}