From 8366c06d46f63b12b88abaddb0ff7a6b6dda75a4 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 15 Apr 2020 15:13:14 -0300 Subject: QCborValue: add tests of parsing invalid ISO date-time strings We rely on QDateTime::fromString being proper, so this is not extensive testing. Change-Id: Ibdc95e9af7bd456a94ecfffd160610cdac5d62e1 Reviewed-by: Thiago Macieira Reviewed-by: Edward Welbourne --- .../serialization/qcborvalue/tst_qcborvalue.cpp | 76 ++++++++++++++++++++-- 1 file changed, 72 insertions(+), 4 deletions(-) diff --git a/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp b/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp index d035ca4ee5..e8acd29bbc 100644 --- a/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp +++ b/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp @@ -126,20 +126,36 @@ inline size_t lengthOf(int) return 1; // encode as byte } +template inline size_t lengthOf(const char (&)[N]) +{ + return N - 1; +} + + +inline size_t lengthOf(const char *str) +{ + return strlen(str); +} + template inline size_t lengthOf(T) { return sizeof(T); } -static void encodeOneAt(char *ptr, int v) +static void encodeOneAt(char *ptr, int v, size_t) { // encode as byte *ptr = char(v); } +static void encodeOneAt(char *ptr, const char *v, size_t size) +{ + memcpy(ptr, v, size); +} + template static typename std::enable_if::value>::type -encodeOneAt(char *ptr, T v) +encodeOneAt(char *ptr, T v, size_t) { qToBigEndian(v, ptr); } @@ -147,7 +163,7 @@ encodeOneAt(char *ptr, T v) template static typename std::enable_if::value || std::is_same::value>::type -encodeOneAt(char *ptr, T v) +encodeOneAt(char *ptr, T v, size_t) { typename QIntegerForSizeof::Unsigned u; memcpy(&u, &v, sizeof(u)); @@ -162,7 +178,7 @@ static char *encodeAt(char *ptr) template static char *encodeAt(char *ptr, Arg0 a0, Args... a) { - encodeOneAt(ptr, a0); + encodeOneAt(ptr, a0, lengthOf(a0)); return encodeAt(ptr + lengthOf(a0), a...); } @@ -1778,6 +1794,15 @@ void tst_QCborValue::fromCbor_data() QTest::newRow("DateTime:NoMilli") << QCborValue(QDateTime::fromSecsSinceEpoch(1515565477, Qt::UTC)) << raw("\xc0\x74" "2018-01-10T06:24:37Z"); + // date-only is only permitted local time + QTest::newRow("DateTime:NoTime:Local") << QCborValue(QDateTime(QDate(2020, 4, 15), QTime(0, 0), Qt::LocalTime)) + << raw("\xc0\x6a" "2020-04-15"); + QTest::newRow("DateTime:24:00:00") << QCborValue(QDateTime(QDate(2020, 4, 16), QTime(0, 0), Qt::UTC)) + << raw("\xc0\x74" "2020-04-15T24:00:00Z"); + QTest::newRow("DateTime:+00:00") << QCborValue(QDateTime::fromMSecsSinceEpoch(1515565477125, Qt::UTC)) + << raw("\xc0\x78\x1d" "2018-01-10T06:24:37.125+00:00"); + QTest::newRow("DateTime:+01:00") << QCborValue(QDateTime::fromMSecsSinceEpoch(1515565477125, Qt::OffsetFromUTC, 60*60)) + << raw("\xc0\x78\x1d" "2018-01-10T07:24:37.125+01:00"); QTest::newRow("UnixTime_t:Integer") << QCborValue(QDateTime::fromSecsSinceEpoch(1515565477, Qt::UTC)) << raw("\xc1\x1a\x5a\x55\xb1\xa5"); QTest::newRow("UnixTime_t:Double") << QCborValue(QDateTime::fromMSecsSinceEpoch(1515565477125, Qt::UTC)) @@ -1985,6 +2010,49 @@ void tst_QCborValue::extendedTypeValidation_data() << encode(0xc1, 0x1b, quint64(dt.toSecsSinceEpoch())) << QCborValue(QCborKnownTags::UnixTime_t, dt.toSecsSinceEpoch()); } + + // Invalid ISO date/time strings + { + auto add = [](const char *tag, const char *str) { + QByteArray raw; + if (strlen(str) < 0x18) + raw = encode(0xc0, 0x60 + int(strlen(str)), str); + else + raw = encode(0xc0, 0x78, quint8(strlen(str)), str); + QTest::addRow("DateTime:%s", tag) + << raw << QCborValue(QCborKnownTags::DateTimeString, QString(str)); + }; + // tst_QDateTime::fromStringDateFormat has more tests + add("junk", "jjj"); + add("zoned-date-only", "2020-04-15Z"); + add("month-13", "2020-13-01T00:00:00Z"); + add("negative-month", "2020--1-01T00:00:00Z"); + add("jan-32", "2020-01-32T00:00:00Z"); + add("apr-31", "2020-04-31T00:00:00Z"); + add("feb-30", "2020-02-30T00:00:00Z"); + add("feb-29-nonleap", "2021-02-29T00:00:00Z"); + add("negative-day", "2020-01--1T00:00:00Z"); + add("bad-separator", "2020-04-15j13:30:59Z"); + add("hour-25", "2020-04-15T25:00:00Z"); + add("negative-hour", "2020-04-15T-1:00:00Z"); + add("minute-60", "2020-04-15T23:60:00Z"); + add("negative-minute", "2020-04-15T23:-1:00Z"); + add("second-60", "2020-04-15T23:59:60Z"); // not a leap second + add("negative-second", "2020-04-15T23:59:-1Z"); + add("negative-milli", "2020-04-15T23.59:59.-1Z"); + + // walking null + char dt[] = "2020-04-15T17:33:32.125Z"; + quint8 len = strlen(dt); + for (int i = 0; i < int(len); ++i) { + char c = '\0'; + qSwap(c, dt[i]); + QTest::addRow("DateTime:Null-at-%d", i) + << encode(0xc0, 0x78, len) + QByteArray(dt, len) + << QCborValue(QCborKnownTags::DateTimeString, QLatin1String(dt, len)); + qSwap(c, dt[i]); + } + } } void tst_QCborValue::extendedTypeValidation() -- cgit v1.2.3