Correctly throw exception on invalid dates

This commit is contained in:
Alexey Milovidov 2021-07-02 03:07:23 +03:00
parent 7a993404b4
commit b33d91412d
4 changed files with 40 additions and 13 deletions

View File

@ -765,7 +765,7 @@ ReturnType readDateTextFallback(LocalDate & date, ReadBuffer & buf)
auto ignore_delimiter = [&]
{
if (!buf.eof())
if (!buf.eof() && !isNumericASCII(*buf.position()))
{
++buf.position();
return true;

View File

@ -572,27 +572,43 @@ inline ReturnType readDateTextImpl(LocalDate & date, ReadBuffer & buf)
/// Optimistic path, when whole value is in buffer.
if (!buf.eof() && buf.position() + 10 <= buf.buffer().end())
{
UInt16 year = (buf.position()[0] - '0') * 1000 + (buf.position()[1] - '0') * 100 + (buf.position()[2] - '0') * 10 + (buf.position()[3] - '0');
buf.position() += 5;
char * pos = buf.position();
UInt8 month = buf.position()[0] - '0';
if (isNumericASCII(buf.position()[1]))
/// YYYY-MM-DD
/// YYYY-MM-D
/// YYYY-M-DD
/// YYYY-M-D
/// The delimiters can be arbitrary characters, like YYYY/MM!DD, but obviously not digits.
UInt16 year = (pos[0] - '0') * 1000 + (pos[1] - '0') * 100 + (pos[2] - '0') * 10 + (pos[3] - '0');
pos += 5;
if (isNumericASCII(pos[-1]))
return ReturnType(false);
UInt8 month = pos[0] - '0';
if (isNumericASCII(pos[1]))
{
month = month * 10 + buf.position()[1] - '0';
buf.position() += 3;
month = month * 10 + pos[1] - '0';
pos += 3;
}
else
buf.position() += 2;
pos += 2;
UInt8 day = buf.position()[0] - '0';
if (isNumericASCII(buf.position()[1]))
if (isNumericASCII(pos[-1]))
return ReturnType(false);
UInt8 day = pos[0] - '0';
if (isNumericASCII(pos[1]))
{
day = day * 10 + buf.position()[1] - '0';
buf.position() += 2;
day = day * 10 + pos[1] - '0';
pos += 2;
}
else
buf.position() += 1;
pos += 1;
buf.position() = pos;
date = LocalDate(year, month, day);
return ReturnType(true);
}

View File

@ -0,0 +1 @@
2019-07-08

View File

@ -0,0 +1,10 @@
SELECT toDate('07-08-2019'); -- { serverError 6 }
SELECT toDate('2019-0708'); -- { serverError 38 }
SELECT toDate('201907-08'); -- { serverError 38 }
SELECT toDate('2019^7^8');
CREATE TEMPORARY TABLE test (d Date);
INSERT INTO test VALUES ('2018-01-01');
SELECT * FROM test WHERE d >= '07-08-2019'; -- { serverError 53 }
SELECT * FROM test WHERE d >= '2019-07-08';