summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjason.piao <jason.piao@mongodb.com>2019-07-12 18:18:25 -0400
committerjason.piao <jason.piao@mongodb.com>2019-08-15 14:38:41 -0400
commit575f10c0c89e18537255d3814c817771ff16d127 (patch)
treed1bb8c4893f14285d475a356998a778637416f54
parent987b2e6e5ab2b2d1b8ec0e1a041147f3ff55e730 (diff)
downloadmongo-575f10c0c89e18537255d3814c817771ff16d127.tar.gz
SERVER-41868 add timelib fuzzer
-rw-r--r--src/mongo/db/query/datetime/SConscript10
-rw-r--r--src/mongo/db/query/datetime/date_time_support.cpp10
-rw-r--r--src/mongo/db/query/datetime/date_time_support.h2
-rw-r--r--src/mongo/db/query/datetime/date_time_support_fuzzer.cpp97
4 files changed, 119 insertions, 0 deletions
diff --git a/src/mongo/db/query/datetime/SConscript b/src/mongo/db/query/datetime/SConscript
index c9ca7cc4d20..62c21d259b7 100644
--- a/src/mongo/db/query/datetime/SConscript
+++ b/src/mongo/db/query/datetime/SConscript
@@ -38,3 +38,13 @@ timeZoneEnv.CppUnitTest(
'date_time_support',
]
)
+
+timeZoneEnv.CppLibfuzzerTest(
+ target='date_time_support_fuzzer',
+ source=[
+ 'date_time_support_fuzzer.cpp',
+ ],
+ LIBDEPS=[
+ 'date_time_support',
+ ]
+)
diff --git a/src/mongo/db/query/datetime/date_time_support.cpp b/src/mongo/db/query/datetime/date_time_support.cpp
index 1705bb600b2..f98dcfac779 100644
--- a/src/mongo/db/query/datetime/date_time_support.cpp
+++ b/src/mongo/db/query/datetime/date_time_support.cpp
@@ -364,6 +364,16 @@ TimeZone TimeZoneDatabase::getTimeZone(StringData timeZoneId) const {
str::stream() << "unrecognized time zone identifier: \"" << timeZoneId << "\"");
}
+std::vector<std::string> TimeZoneDatabase::getTimeZoneStrings() const {
+ std::vector<std::string> timeZoneStrings = {};
+
+ for (auto const& timezone : _timeZones) {
+ timeZoneStrings.push_back(timezone.first);
+ }
+
+ return timeZoneStrings;
+}
+
void TimeZone::adjustTimeZone(timelib_time* timelibTime) const {
if (isTimeZoneIDZone()) {
timelib_set_timezone(timelibTime, _tzInfo.get());
diff --git a/src/mongo/db/query/datetime/date_time_support.h b/src/mongo/db/query/datetime/date_time_support.h
index f5efdcb8fc3..be93ae1c9c4 100644
--- a/src/mongo/db/query/datetime/date_time_support.h
+++ b/src/mongo/db/query/datetime/date_time_support.h
@@ -409,6 +409,8 @@ public:
*/
TimeZoneDatabase(std::unique_ptr<_timelib_tzdb, TimeZoneDBDeleter> timeZoneDatabase);
+ std::vector<std::string> getTimeZoneStrings() const;
+
private:
/**
* Populates '_timeZones' with parsed time zone rules for each timezone specified by
diff --git a/src/mongo/db/query/datetime/date_time_support_fuzzer.cpp b/src/mongo/db/query/datetime/date_time_support_fuzzer.cpp
new file mode 100644
index 00000000000..1214b776fb2
--- /dev/null
+++ b/src/mongo/db/query/datetime/date_time_support_fuzzer.cpp
@@ -0,0 +1,97 @@
+/**
+ * Copyright (C) 2019-present MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the Server Side Public License, version 1,
+ * as published by MongoDB, Inc.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * Server Side Public License for more details.
+ *
+ * You should have received a copy of the Server Side Public License
+ * along with this program. If not, see
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the Server Side Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
+
+#include <string>
+
+#include "boost/none_t.hpp"
+
+#include "mongo/base/data_range_cursor.h"
+#include "mongo/db/query/datetime/date_time_support.h"
+
+
+extern "C" int LLVMFuzzerTestOneInput(const char* Data, size_t Size) try {
+ // Need at least 9 bytes: 1 control byte and 8 bytes for pivot
+ if (Size < 9) {
+ return 0;
+ }
+
+ static const mongo::TimeZoneDatabase timeZoneDatabase{};
+ static const std::vector<std::string> timezones = timeZoneDatabase.getTimeZoneStrings();
+ static const std::array<boost::optional<std::string>, 6> formats = {
+ std::string("%Y-%m-%dT%H:%M:%S.%L"),
+ std::string("%Y/%m/%d %H:%M:%S:%L"),
+ std::string("%Y-%m-%d %H:%M:%S:%L"),
+ std::string("%Y/%m/%d %H %M %S %L"),
+ std::string(""),
+ boost::none};
+
+ mongo::ConstDataRangeCursor drc(Data, Size);
+
+ // use this to determine index and pivot
+ uint8_t controlByte = drc.readAndAdvance<uint8_t>();
+ uint64_t pivotByte = drc.readAndAdvance<uint64_t>();
+ auto newSize = drc.length();
+
+ const mongo::TimeZone timeZone =
+ timeZoneDatabase.getTimeZone(timezones[pivotByte % timezones.size()]);
+
+ std::string str = std::string(drc.data(), newSize);
+
+ boost::optional<std::string> strFormat;
+
+ // 16% of the time, random bytes will be fed into the format arg
+ uint8_t index = controlByte % (formats.size() + 1);
+ if (index < formats.size()) {
+ strFormat = formats[index];
+ } else {
+ // use a pivot so we can vary str and strFormat lengths
+ uint64_t pivot;
+
+ if (newSize == 0) {
+ pivot = 0;
+ } else {
+ pivot = pivotByte % newSize;
+ }
+
+ strFormat = str.substr(pivot, newSize - pivot);
+ str = str.substr(0, pivot);
+ }
+
+ try {
+ timeZoneDatabase.fromString(str, timeZone, boost::optional<mongo::StringData>(strFormat));
+ } catch (const mongo::AssertionException&) {
+ }
+
+ timeZoneDatabase.getTimeZone(str);
+
+ return 0;
+
+} catch (const mongo::AssertionException&) {
+ return 0;
+}