diff options
Diffstat (limited to 'absl/time/internal/cctz/src')
-rw-r--r-- | absl/time/internal/cctz/src/time_zone_format.cc | 22 | ||||
-rw-r--r-- | absl/time/internal/cctz/src/time_zone_format_test.cc | 5 | ||||
-rw-r--r-- | absl/time/internal/cctz/src/time_zone_libc.cc | 9 | ||||
-rw-r--r-- | absl/time/internal/cctz/src/tzfile.h | 8 |
4 files changed, 31 insertions, 13 deletions
diff --git a/absl/time/internal/cctz/src/time_zone_format.cc b/absl/time/internal/cctz/src/time_zone_format.cc index 2e02233c..d8cb0474 100644 --- a/absl/time/internal/cctz/src/time_zone_format.cc +++ b/absl/time/internal/cctz/src/time_zone_format.cc @@ -654,14 +654,23 @@ const char* ParseTM(const char* dp, const char* fmt, std::tm* tm) { } // Sets year, tm_mon and tm_mday given the year, week_num, and tm_wday, -// and the day on which weeks are defined to start. -void FromWeek(int week_num, weekday week_start, year_t* year, std::tm* tm) { +// and the day on which weeks are defined to start. Returns false if year +// would need to move outside its bounds. +bool FromWeek(int week_num, weekday week_start, year_t* year, std::tm* tm) { const civil_year y(*year % 400); civil_day cd = prev_weekday(y, week_start); // week 0 cd = next_weekday(cd - 1, FromTmWday(tm->tm_wday)) + (week_num * 7); - *year += cd.year() - y.year(); + if (const year_t shift = cd.year() - y.year()) { + if (shift > 0) { + if (*year > std::numeric_limits<year_t>::max() - shift) return false; + } else { + if (*year < std::numeric_limits<year_t>::min() - shift) return false; + } + *year += shift; + } tm->tm_mon = cd.month() - 1; tm->tm_mday = cd.day(); + return true; } } // namespace @@ -965,7 +974,12 @@ bool parse(const std::string& format, const std::string& input, } // Compute year, tm.tm_mon and tm.tm_mday if we parsed a week number. - if (week_num != -1) FromWeek(week_num, week_start, &year, &tm); + if (week_num != -1) { + if (!FromWeek(week_num, week_start, &year, &tm)) { + if (err != nullptr) *err = "Out-of-range field"; + return false; + } + } const int month = tm.tm_mon + 1; civil_second cs(year, month, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); diff --git a/absl/time/internal/cctz/src/time_zone_format_test.cc b/absl/time/internal/cctz/src/time_zone_format_test.cc index e625a839..a11f93e2 100644 --- a/absl/time/internal/cctz/src/time_zone_format_test.cc +++ b/absl/time/internal/cctz/src/time_zone_format_test.cc @@ -1481,6 +1481,11 @@ TEST(Parse, WeekYearShift) { EXPECT_EQ(exp, tp); EXPECT_TRUE(parse("%Y-%W-%w", "2020-52-5", utc, &tp)); EXPECT_EQ(exp, tp); + + // Slipping into the previous/following calendar years should fail when + // we're already at the extremes. + EXPECT_FALSE(parse("%Y-%U-%u", "-9223372036854775808-0-7", utc, &tp)); + EXPECT_FALSE(parse("%Y-%U-%u", "9223372036854775807-53-7", utc, &tp)); } TEST(Parse, MaxRange) { diff --git a/absl/time/internal/cctz/src/time_zone_libc.cc b/absl/time/internal/cctz/src/time_zone_libc.cc index 47cf84c6..3fcc75bd 100644 --- a/absl/time/internal/cctz/src/time_zone_libc.cc +++ b/absl/time/internal/cctz/src/time_zone_libc.cc @@ -223,11 +223,10 @@ time_zone::civil_lookup TimeZoneLibC::MakeTime(const civil_second& cs) const { civil_second() + ToUnixSeconds(time_point<seconds>::min()); static const civil_second max_tp_cs = civil_second() + ToUnixSeconds(time_point<seconds>::max()); - const time_point<seconds> tp = - (cs < min_tp_cs) - ? time_point<seconds>::min() - : (cs > max_tp_cs) ? time_point<seconds>::max() - : FromUnixSeconds(cs - civil_second()); + const time_point<seconds> tp = (cs < min_tp_cs) ? time_point<seconds>::min() + : (cs > max_tp_cs) + ? time_point<seconds>::max() + : FromUnixSeconds(cs - civil_second()); return {time_zone::civil_lookup::UNIQUE, tp, tp, tp}; } diff --git a/absl/time/internal/cctz/src/tzfile.h b/absl/time/internal/cctz/src/tzfile.h index 269fa36c..659f84cf 100644 --- a/absl/time/internal/cctz/src/tzfile.h +++ b/absl/time/internal/cctz/src/tzfile.h @@ -108,15 +108,15 @@ struct tzhead { #ifndef TZ_MAX_TYPES /* This must be at least 17 for Europe/Samara and Europe/Vilnius. */ #define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */ -#endif /* !defined TZ_MAX_TYPES */ +#endif /* !defined TZ_MAX_TYPES */ #ifndef TZ_MAX_CHARS #define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */ - /* (limited by what unsigned chars can hold) */ -#endif /* !defined TZ_MAX_CHARS */ +/* (limited by what unsigned chars can hold) */ +#endif /* !defined TZ_MAX_CHARS */ #ifndef TZ_MAX_LEAPS #define TZ_MAX_LEAPS 50 /* Maximum number of leap second corrections */ -#endif /* !defined TZ_MAX_LEAPS */ +#endif /* !defined TZ_MAX_LEAPS */ #endif /* !defined TZFILE_H */ |