diff options
author | Ed Tanous <edtanous@google.com> | 2022-01-11 21:50:23 +0300 |
---|---|---|
committer | Nan Zhou <nanzhoumails@gmail.com> | 2022-01-25 06:12:38 +0300 |
commit | 22ce5458073055db03e4288187116486eaaa64dc (patch) | |
tree | d751884e36e3f1c2ee672f6b871c6dc2f36f264b | |
parent | 8d4c4875dd530064319bbee9e2b7ad08fcde099a (diff) | |
download | bmcweb-22ce5458073055db03e4288187116486eaaa64dc.tar.xz |
Fix Boost exceptions in GetDateTime series
In cases when the input time is too large, we return the maximum
supported date in the ISO Extended format.
Tested: Unit tests pass
Signed-off-by: Nan Zhou <nanzhoumails@gmail.com>
Change-Id: I0dcd60d10d4357bd8700f0dbc1ef86d94bcc82bb
-rw-r--r-- | http/ut/utility_test.cpp | 53 | ||||
-rw-r--r-- | http/utility.hpp | 24 |
2 files changed, 45 insertions, 32 deletions
diff --git a/http/ut/utility_test.cpp b/http/ut/utility_test.cpp index 4748c25712..5dafdce446 100644 --- a/http/ut/utility_test.cpp +++ b/http/ut/utility_test.cpp @@ -2,11 +2,16 @@ #include "gmock/gmock.h" +namespace crow::utility +{ +namespace +{ + TEST(Utility, Base64DecodeAuthString) { std::string authString("dXNlcm40bWU6cGFzc3cwcmQ="); std::string result; - EXPECT_TRUE(crow::utility::base64Decode(authString, result)); + EXPECT_TRUE(base64Decode(authString, result)); EXPECT_EQ(result, "usern4me:passw0rd"); } @@ -14,7 +19,7 @@ TEST(Utility, Base64DecodeNonAscii) { std::string junkString("\xff\xee\xdd\xcc\x01\x11\x22\x33"); std::string result; - EXPECT_FALSE(crow::utility::base64Decode(junkString, result)); + EXPECT_FALSE(base64Decode(junkString, result)); } TEST(Utility, Base64EncodeString) @@ -22,28 +27,28 @@ TEST(Utility, Base64EncodeString) using namespace std::string_literals; std::string encoded; - encoded = crow::utility::base64encode(""); + encoded = base64encode(""); EXPECT_EQ(encoded, ""); - encoded = crow::utility::base64encode("f"); + encoded = base64encode("f"); EXPECT_EQ(encoded, "Zg=="); - encoded = crow::utility::base64encode("f0"); + encoded = base64encode("f0"); EXPECT_EQ(encoded, "ZjA="); - encoded = crow::utility::base64encode("f0\0"s); + encoded = base64encode("f0\0"s); EXPECT_EQ(encoded, "ZjAA"); - encoded = crow::utility::base64encode("f0\0 "s); + encoded = base64encode("f0\0 "s); EXPECT_EQ(encoded, "ZjAAIA=="); - encoded = crow::utility::base64encode("f0\0 B"s); + encoded = base64encode("f0\0 B"s); EXPECT_EQ(encoded, "ZjAAIEI="); - encoded = crow::utility::base64encode("f0\0 Ba"s); + encoded = base64encode("f0\0 Ba"s); EXPECT_EQ(encoded, "ZjAAIEJh"); - encoded = crow::utility::base64encode("f0\0 Bar"s); + encoded = base64encode("f0\0 Bar"s); EXPECT_EQ(encoded, "ZjAAIEJhcg=="); } @@ -51,9 +56,9 @@ TEST(Utility, Base64EncodeDecodeString) { using namespace std::string_literals; std::string data("Data fr\0m 90 reading a \nFile"s); - std::string encoded = crow::utility::base64encode(data); + std::string encoded = base64encode(data); std::string decoded; - EXPECT_TRUE(crow::utility::base64Decode(encoded, decoded)); + EXPECT_TRUE(base64Decode(encoded, decoded)); EXPECT_EQ(data, decoded); } @@ -67,19 +72,16 @@ TEST(Utility, GetDateTimeStdtime) // epoch EXPECT_EQ(getDateTimeStdtime(std::time_t{0}), "1970-01-01T00:00:00+00:00"); - // some time in the past after the epoch // Limits EXPECT_EQ(getDateTimeStdtime(std::numeric_limits<std::time_t>::max()), - "1969-12-31T23:59:59+00:00"); + "9999-12-31T23:59:59+00:00"); EXPECT_EQ(getDateTimeStdtime(std::numeric_limits<std::time_t>::min()), "1970-01-01T00:00:00+00:00"); } -TEST(Utility, getDateTimeUint) +TEST(Utility, GetDateTimeUint) { - using crow::utility::getDateTimeUint; - EXPECT_EQ(getDateTimeUint(uint64_t{1638312095}), "2021-11-30T22:41:35+00:00"); // some time in the future, beyond 2038 @@ -89,22 +91,21 @@ TEST(Utility, getDateTimeUint) EXPECT_EQ(getDateTimeUint(uint64_t{253402300799}), "9999-12-31T23:59:59+00:00"); - // This test currently throws an exception - // EXPECT_EQ(getDateTimeUint(std::numeric_limits<uint64_t>::max()), ""); + // returns the maximum Redfish date + EXPECT_EQ(getDateTimeUint(std::numeric_limits<uint64_t>::max()), + "9999-12-31T23:59:59+00:00"); EXPECT_EQ(getDateTimeUint(std::numeric_limits<uint64_t>::min()), "1970-01-01T00:00:00+00:00"); } -TEST(Utility, getDateTimeUintMs) +TEST(Utility, GetDateTimeUintMs) { - using crow::utility::getDateTimeUintMs; - - // Note, this is the wrong result, but is here to make sure that we don't - // have worse behavior (ie seg faults, exceptions) when this happens + // returns the maximum Redfish date EXPECT_EQ(getDateTimeUintMs(std::numeric_limits<uint64_t>::max()), - "1969-12-31T23:59:59.999000+00:00"); - + "9999-12-31T23:59:59.999000+00:00"); EXPECT_EQ(getDateTimeUintMs(std::numeric_limits<uint64_t>::min()), "1970-01-01T00:00:00+00:00"); } +} // namespace +} // namespace crow::utility diff --git a/http/utility.hpp b/http/utility.hpp index 41182e4eb4..557926761c 100644 --- a/http/utility.hpp +++ b/http/utility.hpp @@ -577,6 +577,8 @@ inline bool base64Decode(const std::string_view input, std::string& output) namespace details { +constexpr uint64_t maxMilliSeconds = 253402300799999; +constexpr uint64_t maxSeconds = 253402300799; inline std::string getDateTime(boost::posix_time::milliseconds timeSinceEpoch) { boost::posix_time::ptime epoch(boost::gregorian::date(1970, 1, 1)); @@ -586,23 +588,33 @@ inline std::string getDateTime(boost::posix_time::milliseconds timeSinceEpoch) } } // namespace details +// Returns the formatted date time string. +// Note that the maximum supported date is 9999-12-31T23:59:59+00:00, if +// the given |secondsSinceEpoch| is too large, we return the maximum supported +// date. This behavior is to avoid exceptions throwed by Boost. inline std::string getDateTimeUint(uint64_t secondsSinceEpoch) { - boost::posix_time::seconds boostSeconds(secondsSinceEpoch); + + boost::posix_time::seconds boostSeconds( + std::min(secondsSinceEpoch, details::maxSeconds)); return details::getDateTime( boost::posix_time::milliseconds(boostSeconds.total_milliseconds())); } -inline std::string getDateTimeUintMs(uint64_t millisSecondsSinceEpoch) +// Returns the formatted date time string. +// Note that the maximum supported date is 9999-12-31T23:59:59.999+00:00, if +// the given |millisSecondsSinceEpoch| is too large, we return the maximum +// supported date. +inline std::string getDateTimeUintMs(uint64_t milliSecondsSinceEpoch) { - return details::getDateTime( - boost::posix_time::milliseconds(millisSecondsSinceEpoch)); + return details::getDateTime(boost::posix_time::milliseconds( + std::min(details::maxMilliSeconds, milliSecondsSinceEpoch))); } inline std::string getDateTimeStdtime(std::time_t secondsSinceEpoch) { - boost::posix_time::ptime time = - boost::posix_time::from_time_t(secondsSinceEpoch); + boost::posix_time::ptime time = boost::posix_time::from_time_t( + std::min(secondsSinceEpoch, std::time_t{details::maxSeconds})); return boost::posix_time::to_iso_extended_string(time) + "+00:00"; } |