mirror of
https://github.com/znc/znc.git
synced 2026-08-07 17:33:34 +02:00
Merge pull request #2014 from MarkLee131/fix/parseservertime-clamp-range
Utils: reject out-of-range years in ParseServerTime
This commit is contained in:
+13
-2
@@ -568,10 +568,21 @@ CString CUtils::FormatServerTime(const timeval& tv) {
|
||||
|
||||
timeval CUtils::ParseServerTime(const CString& sTime) {
|
||||
using namespace std::chrono;
|
||||
system_clock::time_point tp;
|
||||
cctz::parse("%Y-%m-%dT%H:%M:%E*SZ", sTime, cctz::utc_time_zone(), &tp);
|
||||
struct timeval tv;
|
||||
memset(&tv, 0, sizeof(tv));
|
||||
// Reject obviously out-of-range years up front so we don't hand cctz
|
||||
// an input whose internal `seconds * 1_000_000` conversion would
|
||||
// overflow signed int64 (UB). A 5-digit year is plenty for any
|
||||
// legitimate IRCv3 @time tag.
|
||||
CString sYear = sTime.Token(0, false, "-");
|
||||
if (sYear.length() > 5) {
|
||||
return tv;
|
||||
}
|
||||
system_clock::time_point tp;
|
||||
if (!cctz::parse("%Y-%m-%dT%H:%M:%E*SZ", sTime, cctz::utc_time_zone(),
|
||||
&tp)) {
|
||||
return tv;
|
||||
}
|
||||
microseconds usec = duration_cast<microseconds>(tp.time_since_epoch());
|
||||
tv.tv_sec = usec.count() / 1000000;
|
||||
tv.tv_usec = usec.count() % 1000000;
|
||||
|
||||
@@ -161,6 +161,31 @@ TEST(UtilsTest, ParseServerTime) {
|
||||
tzset();
|
||||
}
|
||||
|
||||
TEST(UtilsTest, ParseServerTimeOutOfRange) {
|
||||
// Years past 5 digits trigger int64 overflow inside cctz' microseconds
|
||||
// conversion (`seconds * 1_000_000`). Reject up front (#2008).
|
||||
timeval tv = CUtils::ParseServerTime("999999-01-01T00:00:00.000Z");
|
||||
EXPECT_EQ(tv.tv_sec, 0);
|
||||
EXPECT_EQ(tv.tv_usec, 0);
|
||||
|
||||
tv = CUtils::ParseServerTime("12345678-01-01T00:00:00.000Z");
|
||||
EXPECT_EQ(tv.tv_sec, 0);
|
||||
EXPECT_EQ(tv.tv_usec, 0);
|
||||
|
||||
// Junk and empty input still return a zeroed timeval.
|
||||
tv = CUtils::ParseServerTime("");
|
||||
EXPECT_EQ(tv.tv_sec, 0);
|
||||
EXPECT_EQ(tv.tv_usec, 0);
|
||||
|
||||
tv = CUtils::ParseServerTime("not-a-date-at-all");
|
||||
EXPECT_EQ(tv.tv_sec, 0);
|
||||
EXPECT_EQ(tv.tv_usec, 0);
|
||||
|
||||
// Canonical input still parses (regression).
|
||||
tv = CUtils::ParseServerTime("2011-10-19T16:40:51.620Z");
|
||||
EXPECT_EQ(CUtils::FormatServerTime(tv), "2011-10-19T16:40:51.620Z");
|
||||
}
|
||||
|
||||
class TimeTest : public testing::TestWithParam<
|
||||
std::tuple<timeval, CString, CString, CString>> {};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user